~ubuntu-branches/ubuntu/trusty/eglibc/trusty-security

« back to all changes in this revision

Viewing changes to .pc/any/CVE-2015-5277.diff/nss/nss_files/files-XXX.c

  • Committer: Package Import Robot
  • Author(s): Steve Beattie
  • Date: 2016-04-08 23:26:02 UTC
  • Revision ID: package-import@ubuntu.com-20160408232602-694337pzn1m5xgc3
Tags: 2.19-0ubuntu6.8
* SECURITY UPDATE: buffer overflow in gethostbyname_r and related
  functions
  - debian/patches/any/CVE-2015-1781.diff: take alignment padding
    into account when computing if buffer is too small.
  - CVE-2015-1781
* SECURITY UPDATE: glibc Name Service Switch (NSS) denial of sevice
  - debian/patches/any/CVE-2014-8121-1.diff: do not close NSS files
    database during iteration.
  - debian/patches/any/CVE-2014-8121-2.diff: Separate internal state
    between getXXent and getXXbyYY NSS calls.
  - CVE-2014-8121
* SECURITY UPDATE: glibc unbounded stack usage in NaN strtod
  conversion
  - debian/patches/any/CVE-2014-9761-1.diff: Refactor strtod parsing
    of NaN payloads.
  - debian/patches/any/CVE-2014-9761-1.diff:  Fix nan functions
    handling of payload strings
  - CVE-2014-9761
* SECURITY UPDATE: NSS files long line buffer overflow
  - debian/patches/any/CVE-2015-5277.diff: Don't ignore too long
    lines in nss_files
  - CVE-2015-5277
* SECURITY UPDATE: out of range data to strftime() causes segfault
  (denial of service)
  - debian/patches/any/CVE-2015-8776.diff: add range checks to
    strftime() processing
  - CVE-2015-8776
* SECURITY UPDATE: glibc honors LD_POINTER_GUARD env for setuid
  AT_SECURE programs (e.g. setuid), allowing disabling of pointer
  mangling
  - debian/patches/any/CVE-2015-8777.diff: Always enable pointer
    guard
  - CVE-2015-8777
* SECURITY UPDATE: integer overflow in hcreate and hcreate_r
  - debian/patches/any/CVE-2015-8778.diff: check for large inputs
  - CVE-2015-8778
* SECURITY UPDATE: unbounded stack allocation in catopen()
  - debian/patches/any/CVE-2015-8779.diff: stop using unbounded
    alloca()
  - CVE-2015-8779
* SECURITY UPDATE: Stack overflow in _nss_dns_getnetbyname_r
  - debian/patches/any/CVE-2016-3075.diff: do not make unneeded
    memory copy on the stack.
  - CVE-2016-3075
* SECURITY UPDATE: pt_chown privilege escalation
  - debian/patches/any/CVE-2016-2856.diff: grantpt: trust the kernel
    about pty group and permission mode
  - debian/sysdeps/linux.mk: don't build pt_chown
  - debian/rules.d/debhelper.mk: only install pt_chown when built.
  - CVE-2016-2856, CVE-2013-2207
* debian/debhelper.in/libc.postinst: add reboot notifications for
  security updates (LP: #1546457)
* debian/patches/ubuntu/submitted-no-stack-backtrace.diff: update
  patch to eliminate compiler warning.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Common code for file-based databases in nss_files module.
 
2
   Copyright (C) 1996-2014 Free Software Foundation, Inc.
 
3
   This file is part of the GNU C Library.
 
4
 
 
5
   The GNU C Library is free software; you can redistribute it and/or
 
6
   modify it under the terms of the GNU Lesser General Public
 
7
   License as published by the Free Software Foundation; either
 
8
   version 2.1 of the License, or (at your option) any later version.
 
9
 
 
10
   The GNU C Library is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
   Lesser General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU Lesser General Public
 
16
   License along with the GNU C Library; if not, see
 
17
   <http://www.gnu.org/licenses/>.  */
 
18
 
 
19
#include <stdio.h>
 
20
#include <ctype.h>
 
21
#include <errno.h>
 
22
#include <fcntl.h>
 
23
#include <bits/libc-lock.h>
 
24
#include "nsswitch.h"
 
25
 
 
26
#include <kernel-features.h>
 
27
 
 
28
/* These symbols are defined by the including source file:
 
29
 
 
30
   ENTNAME -- database name of the structure and functions (hostent, pwent).
 
31
   STRUCTURE -- struct name, define only if not ENTNAME (passwd, group).
 
32
   DATABASE -- string of the database file's name ("hosts", "passwd").
 
33
 
 
34
   NEED_H_ERRNO - defined iff an arg `int *herrnop' is used.
 
35
 
 
36
   Also see files-parse.c.
 
37
*/
 
38
 
 
39
#define ENTNAME_r       CONCAT(ENTNAME,_r)
 
40
 
 
41
#define DATAFILE        "/etc/" DATABASE
 
42
 
 
43
#ifdef NEED_H_ERRNO
 
44
# include <netdb.h>
 
45
# define H_ERRNO_PROTO  , int *herrnop
 
46
# define H_ERRNO_ARG    , herrnop
 
47
# define H_ERRNO_SET(val) (*herrnop = (val))
 
48
#else
 
49
# define H_ERRNO_PROTO
 
50
# define H_ERRNO_ARG
 
51
# define H_ERRNO_SET(val) ((void) 0)
 
52
#endif
 
53
 
 
54
#ifndef EXTRA_ARGS
 
55
# define EXTRA_ARGS
 
56
# define EXTRA_ARGS_DECL
 
57
# define EXTRA_ARGS_VALUE
 
58
#endif
 
59
 
 
60
/* Locks the static variables in this file.  */
 
61
__libc_lock_define_initialized (static, lock)
 
62
 
 
63
/* Maintenance of the stream open on the database file.  For getXXent
 
64
   operations the stream needs to be held open across calls, the other
 
65
   getXXbyYY operations all use their own stream.  */
 
66
 
 
67
static FILE *stream;
 
68
 
 
69
/* Open database file if not already opened.  */
 
70
static enum nss_status
 
71
internal_setent (FILE **stream)
 
72
{
 
73
  enum nss_status status = NSS_STATUS_SUCCESS;
 
74
 
 
75
  if (*stream == NULL)
 
76
    {
 
77
      *stream = fopen (DATAFILE, "rce");
 
78
 
 
79
      if (*stream == NULL)
 
80
        status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
 
81
      else
 
82
        {
 
83
#if !defined O_CLOEXEC || !defined __ASSUME_O_CLOEXEC
 
84
# ifdef O_CLOEXEC
 
85
          if (__have_o_cloexec <= 0)
 
86
# endif
 
87
            {
 
88
              /* We have to make sure the file is  `closed on exec'.  */
 
89
              int result;
 
90
              int flags;
 
91
 
 
92
              result = flags = fcntl (fileno (*stream), F_GETFD, 0);
 
93
              if (result >= 0)
 
94
                {
 
95
# ifdef O_CLOEXEC
 
96
                  if (__have_o_cloexec == 0)
 
97
                    __have_o_cloexec = (flags & FD_CLOEXEC) == 0 ? -1 : 1;
 
98
                  if (__have_o_cloexec < 0)
 
99
# endif
 
100
                    {
 
101
                      flags |= FD_CLOEXEC;
 
102
                      result = fcntl (fileno (*stream), F_SETFD, flags);
 
103
                    }
 
104
                }
 
105
              if (result < 0)
 
106
                {
 
107
                  /* Something went wrong.  Close the stream and return a
 
108
                     failure.  */
 
109
                  fclose (*stream);
 
110
                  *stream = NULL;
 
111
                  status = NSS_STATUS_UNAVAIL;
 
112
                }
 
113
            }
 
114
#endif
 
115
        }
 
116
    }
 
117
  else
 
118
    rewind (*stream);
 
119
 
 
120
  return status;
 
121
}
 
122
 
 
123
 
 
124
/* Thread-safe, exported version of that.  */
 
125
enum nss_status
 
126
CONCAT(_nss_files_set,ENTNAME) (int stayopen)
 
127
{
 
128
  enum nss_status status;
 
129
 
 
130
  __libc_lock_lock (lock);
 
131
 
 
132
  status = internal_setent (&stream);
 
133
 
 
134
  __libc_lock_unlock (lock);
 
135
 
 
136
  return status;
 
137
}
 
138
 
 
139
 
 
140
/* Close the database file.  */
 
141
static void
 
142
internal_endent (FILE **stream)
 
143
{
 
144
  if (*stream != NULL)
 
145
    {
 
146
      fclose (*stream);
 
147
      *stream = NULL;
 
148
    }
 
149
}
 
150
 
 
151
 
 
152
/* Thread-safe, exported version of that.  */
 
153
enum nss_status
 
154
CONCAT(_nss_files_end,ENTNAME) (void)
 
155
{
 
156
  __libc_lock_lock (lock);
 
157
 
 
158
  internal_endent (&stream);
 
159
 
 
160
  __libc_lock_unlock (lock);
 
161
 
 
162
  return NSS_STATUS_SUCCESS;
 
163
}
 
164
 
 
165
 
 
166
typedef enum
 
167
{
 
168
  gcr_ok = 0,
 
169
  gcr_error = -1,
 
170
  gcr_overflow = -2
 
171
} get_contents_ret;
 
172
 
 
173
/* Hack around the fact that fgets only accepts int sizes.  */
 
174
static get_contents_ret
 
175
get_contents (char *linebuf, size_t len, FILE *stream)
 
176
{
 
177
  size_t remaining_len = len;
 
178
  char *curbuf = linebuf;
 
179
 
 
180
  do
 
181
    {
 
182
      int curlen = ((remaining_len > (size_t) INT_MAX) ? INT_MAX
 
183
                    : remaining_len);
 
184
      char *p = fgets_unlocked (curbuf, curlen, stream);
 
185
 
 
186
      ((unsigned char *) curbuf)[curlen - 1] = 0xff;
 
187
 
 
188
      /* EOF or read error.  */
 
189
      if (p == NULL)
 
190
        return gcr_error;
 
191
 
 
192
      /* Done reading in the line.  */
 
193
      if (((unsigned char *) curbuf)[curlen - 1] == 0xff)
 
194
        return gcr_ok;
 
195
 
 
196
      /* Drop the terminating '\0'.  */
 
197
      remaining_len -= curlen - 1;
 
198
      curbuf += curlen - 1;
 
199
    }
 
200
  /* fgets copies one less than the input length.  Our last iteration is of
 
201
     REMAINING_LEN and once that is done, REMAINING_LEN is decremented by
 
202
     REMAINING_LEN - 1, leaving the result as 1.  */
 
203
  while (remaining_len > 1);
 
204
 
 
205
  /* This means that the current buffer was not large enough.  */
 
206
  return gcr_overflow;
 
207
}
 
208
 
 
209
/* Parsing the database file into `struct STRUCTURE' data structures.  */
 
210
static enum nss_status
 
211
internal_getent (FILE *stream, struct STRUCTURE *result,
 
212
                 char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO
 
213
                 EXTRA_ARGS_DECL)
 
214
{
 
215
  char *p;
 
216
  struct parser_data *data = (void *) buffer;
 
217
  size_t linebuflen = buffer + buflen - data->linebuffer;
 
218
  int parse_result;
 
219
 
 
220
  if (buflen < sizeof *data + 2)
 
221
    {
 
222
      *errnop = ERANGE;
 
223
      H_ERRNO_SET (NETDB_INTERNAL);
 
224
      return NSS_STATUS_TRYAGAIN;
 
225
    }
 
226
 
 
227
  do
 
228
    {
 
229
      get_contents_ret r = get_contents (data->linebuffer, linebuflen, stream);
 
230
 
 
231
      if (r == gcr_error)
 
232
        {
 
233
          /* End of file or read error.  */
 
234
          H_ERRNO_SET (HOST_NOT_FOUND);
 
235
          return NSS_STATUS_NOTFOUND;
 
236
        }
 
237
 
 
238
      if (r == gcr_overflow)
 
239
        {
 
240
          /* The line is too long.  Give the user the opportunity to
 
241
             enlarge the buffer.  */
 
242
          *errnop = ERANGE;
 
243
          H_ERRNO_SET (NETDB_INTERNAL);
 
244
          return NSS_STATUS_TRYAGAIN;
 
245
        }
 
246
 
 
247
      /* Everything OK.  Now skip leading blanks.  */
 
248
      p = data->linebuffer;
 
249
      while (isspace (*p))
 
250
        ++p;
 
251
    }
 
252
  while (*p == '\0' || *p == '#' /* Ignore empty and comment lines.  */
 
253
         /* Parse the line.  If it is invalid, loop to get the next
 
254
            line of the file to parse.  */
 
255
         || ! (parse_result = parse_line (p, result, data, buflen, errnop
 
256
                                          EXTRA_ARGS)));
 
257
 
 
258
  if (__builtin_expect (parse_result == -1, 0))
 
259
    {
 
260
      H_ERRNO_SET (NETDB_INTERNAL);
 
261
      return NSS_STATUS_TRYAGAIN;
 
262
    }
 
263
 
 
264
  /* Filled in RESULT with the next entry from the database file.  */
 
265
  return NSS_STATUS_SUCCESS;
 
266
}
 
267
 
 
268
 
 
269
/* Return the next entry from the database file, doing locking.  */
 
270
enum nss_status
 
271
CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
 
272
                                  size_t buflen, int *errnop H_ERRNO_PROTO)
 
273
{
 
274
  /* Return next entry in host file.  */
 
275
  enum nss_status status = NSS_STATUS_SUCCESS;
 
276
 
 
277
  __libc_lock_lock (lock);
 
278
 
 
279
  /* Be prepared that the set*ent function was not called before.  */
 
280
  if (stream == NULL)
 
281
    {
 
282
      int save_errno = errno;
 
283
 
 
284
      status = internal_setent (&stream);
 
285
 
 
286
      __set_errno (save_errno);
 
287
    }
 
288
 
 
289
  if (status == NSS_STATUS_SUCCESS)
 
290
    status = internal_getent (stream, result, buffer, buflen, errnop
 
291
                              H_ERRNO_ARG EXTRA_ARGS_VALUE);
 
292
 
 
293
  __libc_lock_unlock (lock);
 
294
 
 
295
  return status;
 
296
}
 
297
 
 
298
/* Macro for defining lookup functions for this file-based database.
 
299
 
 
300
   NAME is the name of the lookup; e.g. `hostbyname'.
 
301
 
 
302
   DB_CHAR, KEYPATTERN, KEYSIZE are ignored here but used by db-XXX.c
 
303
   e.g. `1 + sizeof (id) * 4'.
 
304
 
 
305
   PROTO is the potentially empty list of other parameters.
 
306
 
 
307
   BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result'
 
308
   to the lookup key arguments and does `break;' if they match.  */
 
309
 
 
310
#define DB_LOOKUP(name, db_char, keysize, keypattern, break_if_match, proto...)\
 
311
enum nss_status                                                               \
 
312
_nss_files_get##name##_r (proto,                                              \
 
313
                          struct STRUCTURE *result, char *buffer,             \
 
314
                          size_t buflen, int *errnop H_ERRNO_PROTO)           \
 
315
{                                                                             \
 
316
  enum nss_status status;                                                     \
 
317
  FILE *stream = NULL;                                                        \
 
318
                                                                              \
 
319
  /* Open file.  */                                                           \
 
320
  status = internal_setent (&stream);                                         \
 
321
                                                                              \
 
322
  if (status == NSS_STATUS_SUCCESS)                                           \
 
323
    {                                                                         \
 
324
      while ((status = internal_getent (stream, result, buffer, buflen, errnop \
 
325
                                        H_ERRNO_ARG EXTRA_ARGS_VALUE))        \
 
326
             == NSS_STATUS_SUCCESS)                                           \
 
327
        { break_if_match }                                                    \
 
328
                                                                              \
 
329
      internal_endent (&stream);                                              \
 
330
    }                                                                         \
 
331
                                                                              \
 
332
  return status;                                                              \
 
333
}