diff options
Diffstat (limited to 'lib/libc/gen')
59 files changed, 561 insertions, 260 deletions
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index f64caf0..2232b79 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -5,6 +5,7 @@ .PATH: ${LIBC_SRCTOP}/${LIBC_ARCH}/gen ${LIBC_SRCTOP}/gen SRCS+= __getosreldate.c \ + __pthread_mutex_init_calloc_cb_stub.c \ __xuname.c \ _once_stub.c \ _pthread_stubs.c \ diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 77413d6..ee4d619 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -487,6 +487,7 @@ FBSDprivate_1.0 { _rtld_atfork_post; _rtld_error; /* for private use */ _rtld_get_stack_prot; + _rtld_is_dlopened; _rtld_thread_init; /* for private use */ __elf_phdr_match_addr; _err; @@ -532,6 +533,8 @@ FBSDprivate_1.0 { _libc_sem_post_compat; _libc_sem_getvalue_compat; + __libc_tcdrain; + __elf_aux_vector; __pthread_map_stacks_exec; __fillcontextx; diff --git a/lib/libc/gen/__pthread_mutex_init_calloc_cb_stub.c b/lib/libc/gen/__pthread_mutex_init_calloc_cb_stub.c new file mode 100644 index 0000000..1c566ec --- /dev/null +++ b/lib/libc/gen/__pthread_mutex_init_calloc_cb_stub.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014 The FreeBSD Foundation. + * All rights reserved. + * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <pthread.h> +#include "libc_private.h" + +int +_pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex, + void *(calloc_cb)(size_t, size_t)) +{ + + return (0); +} diff --git a/lib/libc/gen/_once_stub.c b/lib/libc/gen/_once_stub.c index d2acc29..c45565a 100644 --- a/lib/libc/gen/_once_stub.c +++ b/lib/libc/gen/_once_stub.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009 Advanced Computing Technologies LLC + * Copyright (c) 2009 Hudson River Trading LLC * Written by: John H. Baldwin <jhb@FreeBSD.org> * All rights reserved. * diff --git a/lib/libc/gen/_spinlock_stub.c b/lib/libc/gen/_spinlock_stub.c index 47bbfeb..3decf8a 100644 --- a/lib/libc/gen/_spinlock_stub.c +++ b/lib/libc/gen/_spinlock_stub.c @@ -33,51 +33,48 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include "spinlock.h" +#include "libc_private.h" long _atomic_lock_stub(volatile long *); void _spinlock_stub(spinlock_t *); void _spinunlock_stub(spinlock_t *); void _spinlock_debug_stub(spinlock_t *, char *, int); -/* - * Declare weak definitions in case the application is not linked - * with libpthread. - */ __weak_reference(_atomic_lock_stub, _atomic_lock); -__weak_reference(_spinlock_stub, _spinlock); -__weak_reference(_spinunlock_stub, _spinunlock); -__weak_reference(_spinlock_debug_stub, _spinlock_debug); -/* - * This function is a stub for the _atomic_lock function in libpthread. - */ long _atomic_lock_stub(volatile long *lck __unused) { return (0L); } +__weak_reference(_spinlock, _spinlock_debug); +#pragma weak _spinlock +void +_spinlock(spinlock_t *lck) +{ -/* - * This function is a stub for the spinlock function in libpthread. - */ + ((void (*)(spinlock_t *lck))__libc_interposing[INTERPOS_spinlock]) + (lck); + +} + +#pragma weak _spinunlock void -_spinlock_stub(spinlock_t *lck __unused) +_spinunlock(spinlock_t *lck) { + + ((void (*)(spinlock_t *lck))__libc_interposing[INTERPOS_spinunlock]) + (lck); + } -/* - * This function is a stub for the spinunlock function in libpthread. - */ void -_spinunlock_stub(spinlock_t *lck __unused) +__libc_spinlock_stub(spinlock_t *lck __unused) { } -/* - * This function is a stub for the debug spinlock function in libpthread. - */ void -_spinlock_debug_stub(spinlock_t *lck __unused, char *fname __unused, int lineno __unused) +__libc_spinunlock_stub(spinlock_t *lck __unused) { } diff --git a/lib/libc/gen/cap_rights_get.3 b/lib/libc/gen/cap_rights_get.3 index f74d1f7a..a665465 100644 --- a/lib/libc/gen/cap_rights_get.3 +++ b/lib/libc/gen/cap_rights_get.3 @@ -100,10 +100,10 @@ argument points at an invalid address. .El .Sh SEE ALSO .Xr cap_rights_limit 2 , -.Xr cap_rights_init 3 , .Xr errno 2 , .Xr open 2 , .Xr assert 3 , +.Xr cap_rights_init 3 , .Xr err 3 , .Xr memcmp 3 , .Xr memset 3 , diff --git a/lib/libc/gen/directory.3 b/lib/libc/gen/directory.3 index 1e864f8..f0d0f4b 100644 --- a/lib/libc/gen/directory.3 +++ b/lib/libc/gen/directory.3 @@ -28,7 +28,7 @@ .\" @(#)directory.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd July 28, 2014 +.Dd May 6, 2015 .Dt DIRECTORY 3 .Os .Sh NAME @@ -263,8 +263,25 @@ function appeared in function appeared in .Fx 10.0 . .Sh BUGS -The invalidation of +The behaviour of .Fn telldir -tokens when calling +and +.Fn seekdir +is likely to be wrong if there are parallel unlinks happening +and the directory is larger than one page. +There is code to ensure that a .Fn seekdir -is non-standard. +to the location given by a +.Fn telldir +immediately before the last +.Fn readdir +will always set the correct location to return the same value as that last +.Fn readdir +performed. +This is enough for some applications which want to "push back the last entry read" E.g. Samba. +Seeks back to any other location, +other than the beginning of the directory, +may result in unexpected behaviour if deletes are present. +It is hoped that this situation will be resolved with changes to +.Fn getdirentries +and the VFS. diff --git a/lib/libc/gen/disklabel.c b/lib/libc/gen/disklabel.c index bd15a47..8780573 100644 --- a/lib/libc/gen/disklabel.c +++ b/lib/libc/gen/disklabel.c @@ -85,10 +85,13 @@ getdiskbyname(const char *name) cq++, cp++; *cq = '\0'; - if (cgetstr(buf, "ty", &cq) > 0 && strcmp(cq, "removable") == 0) - dp->d_flags |= D_REMOVABLE; - else if (cq && strcmp(cq, "simulated") == 0) - dp->d_flags |= D_RAMDISK; + if (cgetstr(buf, "ty", &cq) > 0) { + if (strcmp(cq, "removable") == 0) + dp->d_flags |= D_REMOVABLE; + else if (cq && strcmp(cq, "simulated") == 0) + dp->d_flags |= D_RAMDISK; + free(cq); + } if (cgetcap(buf, "sf", ':') != NULL) dp->d_flags |= D_BADSECT; @@ -100,9 +103,10 @@ getdiskbyname(const char *name) getnumdflt(dp->d_nsectors, "ns", 0); getnumdflt(dp->d_ncylinders, "nc", 0); - if (cgetstr(buf, "dt", &cq) > 0) + if (cgetstr(buf, "dt", &cq) > 0) { dp->d_type = gettype(cq, dktypenames); - else + free(cq); + } else getnumdflt(dp->d_type, "dt", 0); getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks); getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders); @@ -140,8 +144,11 @@ getdiskbyname(const char *name) pp->p_frag = 8; } getnumdflt(pp->p_fstype, ptype, 0); - if (pp->p_fstype == 0 && cgetstr(buf, ptype, &cq) > 0) - pp->p_fstype = gettype(cq, fstypenames); + if (pp->p_fstype == 0) + if (cgetstr(buf, ptype, &cq) >= 0) { + pp->p_fstype = gettype(cq, fstypenames); + free(cq); + } max = p; } } diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c index ad24bb4..7d28797 100644 --- a/lib/libc/gen/dlfcn.c +++ b/lib/libc/gen/dlfcn.c @@ -149,10 +149,8 @@ static void dl_init_phdr_info(void) { Elf_Auxinfo *auxp; - size_t phent; unsigned int i; - phent = 0; for (auxp = __elf_aux_vector; auxp->a_type != AT_NULL; auxp++) { switch (auxp->a_type) { case AT_BASE: @@ -165,9 +163,6 @@ dl_init_phdr_info(void) phdr_info.dlpi_phdr = (const Elf_Phdr *)auxp->a_un.a_ptr; break; - case AT_PHENT: - phent = auxp->a_un.a_val; - break; case AT_PHNUM: phdr_info.dlpi_phnum = (Elf_Half)auxp->a_un.a_val; break; @@ -233,3 +228,10 @@ _rtld_get_stack_prot(void) return (PROT_EXEC | PROT_READ | PROT_WRITE); } +#pragma weak _rtld_is_dlopened +int +_rtld_is_dlopened(void *arg) +{ + + return (0); +} diff --git a/lib/libc/gen/dlopen.3 b/lib/libc/gen/dlopen.3 index 089e631..1963528 100644 --- a/lib/libc/gen/dlopen.3 +++ b/lib/libc/gen/dlopen.3 @@ -32,7 +32,7 @@ .\" @(#) dlopen.3 1.6 90/01/31 SMI .\" $FreeBSD$ .\" -.Dd December 21, 2011 +.Dd February 14, 2015 .Dt DLOPEN 3 .Os .Sh NAME @@ -236,7 +236,7 @@ as follows, in the given order: The referencing object itself (or the object from which the call to .Fn dlsym is made), if that object was linked using the -.Fl Wsymbolic +.Fl Bsymbolic option to .Xr ld 1 . .It diff --git a/lib/libc/gen/fstab.c b/lib/libc/gen/fstab.c index 6a77abd..c21ceb3 100644 --- a/lib/libc/gen/fstab.c +++ b/lib/libc/gen/fstab.c @@ -181,7 +181,7 @@ fstabscan(void) if (cp != NULL) _fs_fstab.fs_passno = atoi(cp); } - strcpy(subline, _fs_fstab.fs_mntops); + (void)strlcpy(subline, _fs_fstab.fs_mntops, sizeof(subline)); p = subline; for (typexx = 0, cp = strsep(&p, ","); cp; cp = strsep(&p, ",")) { diff --git a/lib/libc/gen/ftok.3 b/lib/libc/gen/ftok.3 index 98f8bad..b819dbd 100644 --- a/lib/libc/gen/ftok.3 +++ b/lib/libc/gen/ftok.3 @@ -64,9 +64,9 @@ function will return -1 if .Fa path does not exist or if it cannot be accessed by the calling process. .Sh SEE ALSO +.Xr msgget 2 , .Xr semget 2 , -.Xr shmget 2 , -.Xr msgget 2 +.Xr shmget 2 .Sh HISTORY The .Fn ftok diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c index 7635fbc..1ca8334 100644 --- a/lib/libc/gen/fts.c +++ b/lib/libc/gen/fts.c @@ -905,12 +905,13 @@ fts_stat(FTS *sp, FTSENT *p, int follow, int dfd) if (ISSET(FTS_LOGICAL) || follow) { if (fstatat(dfd, path, sbp, 0)) { saved_errno = errno; - if (!fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { - errno = 0; - return (FTS_SLNONE); + if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { + p->fts_errno = saved_errno; + goto err; } - p->fts_errno = saved_errno; - goto err; + errno = 0; + if (S_ISLNK(sbp->st_mode)) + return (FTS_SLNONE); } } else if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) { p->fts_errno = errno; diff --git a/lib/libc/gen/ftw.3 b/lib/libc/gen/ftw.3 index ba8859b..df8abab 100644 --- a/lib/libc/gen/ftw.3 +++ b/lib/libc/gen/ftw.3 @@ -87,8 +87,9 @@ A directory which cannot be read. The directory will not be descended into. .It Dv FTW_DP A directory being visited in post-order -.Fn ( nftw -only). +.Po Fn nftw +only +.Pc . .It Dv FTW_NS A file for which no .Xr stat 2 @@ -100,8 +101,9 @@ structure are undefined. A symbolic link. .It Dv FTW_SLN A symbolic link with a non-existent target -.Fn ( nftw -only). +.Po Fn nftw +only +.Pc . .El .Pp The diff --git a/lib/libc/gen/getcap.3 b/lib/libc/gen/getcap.3 index 73826ae..c3a9ce8 100644 --- a/lib/libc/gen/getcap.3 +++ b/lib/libc/gen/getcap.3 @@ -137,9 +137,10 @@ It must be called before the call. If a sequential access is being performed (see below), it must be called before the first sequential access call -.Fn ( cgetfirst +.Po Fn cgetfirst or -.Fn cgetnext ) , +.Fn cgetnext +.Pc , or be directly preceded by a .Fn cgetclose call. diff --git a/lib/libc/gen/getgrent.c b/lib/libc/gen/getgrent.c index f9480c3..1f4d7e9 100644 --- a/lib/libc/gen/getgrent.c +++ b/lib/libc/gen/getgrent.c @@ -896,7 +896,7 @@ files_group(void *retval, void *mdata, va_list ap) break; pos = ftello(st->fp); } - if (!stayopen && st->fp != NULL) { + if (st->fp != NULL && !stayopen) { fclose(st->fp); st->fp = NULL; } @@ -1173,8 +1173,10 @@ nis_group(void *retval, void *mdata, va_list ap) * terminator, alignment padding, and one (char *) * pointer for the member list terminator. */ - if (resultlen >= bufsize - _ALIGNBYTES - sizeof(char *)) + if (resultlen >= bufsize - _ALIGNBYTES - sizeof(char *)) { + free(result); goto erange; + } memcpy(buffer, result, resultlen); buffer[resultlen] = '\0'; free(result); @@ -1450,7 +1452,7 @@ docompat: pos = ftello(st->fp); } fin: - if (!stayopen && st->fp != NULL) { + if (st->fp != NULL && !stayopen) { fclose(st->fp); st->fp = NULL; } diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c index f729cdf..09a6247 100644 --- a/lib/libc/gen/getpwent.c +++ b/lib/libc/gen/getpwent.c @@ -815,7 +815,7 @@ files_passwd(void *retval, void *mdata, va_list ap) size_t bufsize, namesize; uid_t uid; uint32_t store; - int rv, stayopen, *errnop; + int rv, stayopen = 0, *errnop; name = NULL; uid = (uid_t)-1; @@ -921,7 +921,7 @@ files_passwd(void *retval, void *mdata, va_list ap) errnop); } while (how == nss_lt_all && !(rv & NS_TERMINATE)); fin: - if (!stayopen && st->db != NULL) { + if (st->db != NULL && !stayopen) { (void)st->db->close(st->db); st->db = NULL; } @@ -1392,8 +1392,10 @@ nis_passwd(void *retval, void *mdata, va_list ap) continue; } } - if (resultlen >= bufsize) + if (resultlen >= bufsize) { + free(result); goto erange; + } memcpy(buffer, result, resultlen); buffer[resultlen] = '\0'; free(result); @@ -1940,7 +1942,7 @@ docompat: break; } fin: - if (!stayopen && st->db != NULL) { + if (st->db != NULL && !stayopen) { (void)st->db->close(st->db); st->db = NULL; } diff --git a/lib/libc/gen/getutxent.3 b/lib/libc/gen/getutxent.3 index 120f4a0..85c37b1 100644 --- a/lib/libc/gen/getutxent.3 +++ b/lib/libc/gen/getutxent.3 @@ -475,4 +475,4 @@ They replaced the .In utmp.h interface. .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/nice.3 b/lib/libc/gen/nice.3 index 9c39b78..b04c8f4 100644 --- a/lib/libc/gen/nice.3 +++ b/lib/libc/gen/nice.3 @@ -28,7 +28,7 @@ .\" @(#)nice.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd February 28, 2015 .Dt NICE 3 .Os .Sh NAME @@ -48,20 +48,48 @@ This interface is obsoleted by .Pp The .Fn nice -function obtains the scheduling priority of the process -from the system and sets it to the priority value specified in -.Fa incr . +function adds +.Fa incr +to the scheduling priority of the process. The priority is a value in the range -20 to 20. The default priority is 0; lower priorities cause more favorable scheduling. Only the super-user may lower priorities. .Pp Children inherit the priority of their parent processes via .Xr fork 2 . +.Sh RETURN VALUES +Upon successful completion, +.Fn nice +returns 0, and +.Va errno +is unchanged. +Otherwise, \-1 is returned, the process' nice value is not changed, and +.Va errno +is set to indicate the error. +.Sh ERRORS +The +.Fn nice +function will fail if: +.Bl -tag -width Er +.It Bq Er EPERM +The +.Fa incr +argument is negative and the caller does not have appropriate privileges. +.El .Sh SEE ALSO .Xr nice 1 , .Xr fork 2 , .Xr setpriority 2 , .Xr renice 8 +.Sh STANDARDS +The +.Fn nice +function conforms to +.St -p1003.1-2008 +except for the return value. +This implementation returns 0 upon successful completion but +the standard requires returning the new nice value, +which could be \-1. .Sh HISTORY A .Fn nice diff --git a/lib/libc/gen/nice.c b/lib/libc/gen/nice.c index e8375e8..ba9524b 100644 --- a/lib/libc/gen/nice.c +++ b/lib/libc/gen/nice.c @@ -43,14 +43,20 @@ __FBSDID("$FreeBSD$"); * Backwards compatible nice. */ int -nice(incr) - int incr; +nice(int incr) { - int prio; + int saverrno, prio; + saverrno = errno; errno = 0; prio = getpriority(PRIO_PROCESS, 0); - if (prio == -1 && errno) + if (prio == -1 && errno != 0) return (-1); - return (setpriority(PRIO_PROCESS, 0, prio + incr)); + if (setpriority(PRIO_PROCESS, 0, prio + incr) == -1) { + if (errno == EACCES) + errno = EPERM; + return (-1); + } + errno = saverrno; + return (0); } diff --git a/lib/libc/gen/nlist.c b/lib/libc/gen/nlist.c index bdadd55..ec878c5 100644 --- a/lib/libc/gen/nlist.c +++ b/lib/libc/gen/nlist.c @@ -47,7 +47,10 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include "un-namespace.h" +/* There is no a.out support on arm64 */ +#ifndef __aarch64__ #define _NLIST_DO_AOUT +#endif #define _NLIST_DO_ELF #ifdef _NLIST_DO_ELF diff --git a/lib/libc/gen/pause.c b/lib/libc/gen/pause.c index 51706cf..ef48c1c 100644 --- a/lib/libc/gen/pause.c +++ b/lib/libc/gen/pause.c @@ -33,10 +33,10 @@ static char sccsid[] = "@(#)pause.c 8.1 (Berkeley) 6/4/93"; #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include "namespace.h" #include <signal.h> #include <unistd.h> -#include "un-namespace.h" + +#include "libc_private.h" /* * Backwards compatible pause. @@ -46,9 +46,10 @@ __pause(void) { sigset_t oset; - if (_sigprocmask(SIG_BLOCK, NULL, &oset) == -1) + if (sigprocmask(SIG_BLOCK, NULL, &oset) == -1) return (-1); - return (_sigsuspend(&oset)); + return (sigsuspend(&oset)); } + __weak_reference(__pause, pause); __weak_reference(__pause, _pause); diff --git a/lib/libc/gen/posix_spawn.3 b/lib/libc/gen/posix_spawn.3 index dd5bd2b..2c9131b 100644 --- a/lib/libc/gen/posix_spawn.3 +++ b/lib/libc/gen/posix_spawn.3 @@ -413,6 +413,10 @@ including trying to close a descriptor that is not open. .Xr execve 2 , .Xr fcntl 2 , .Xr open 2 , +.Xr sched_setparam 2 , +.Xr sched_setscheduler 2 , +.Xr setpgid 2 , +.Xr vfork 2 , .Xr posix_spawn_file_actions_addclose 3 , .Xr posix_spawn_file_actions_adddup2 3 , .Xr posix_spawn_file_actions_addopen 3 , @@ -431,11 +435,7 @@ including trying to close a descriptor that is not open. .Xr posix_spawnattr_setschedparam 3 , .Xr posix_spawnattr_setschedpolicy 3 , .Xr posix_spawnattr_setsigdefault 3 , -.Xr posix_spawnattr_setsigmask 3 , -.Xr sched_setparam 2 , -.Xr sched_setscheduler 2 , -.Xr setpgid 2 , -.Xr vfork 2 +.Xr posix_spawnattr_setsigmask 3 .Sh STANDARDS The .Fn posix_spawn @@ -457,4 +457,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/posix_spawn_file_actions_addopen.3 b/lib/libc/gen/posix_spawn_file_actions_addopen.3 index b28f396..0b57999b 100644 --- a/lib/libc/gen/posix_spawn_file_actions_addopen.3 +++ b/lib/libc/gen/posix_spawn_file_actions_addopen.3 @@ -200,4 +200,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/posix_spawn_file_actions_init.3 b/lib/libc/gen/posix_spawn_file_actions_init.3 index eda2a1d..380eed7 100644 --- a/lib/libc/gen/posix_spawn_file_actions_init.3 +++ b/lib/libc/gen/posix_spawn_file_actions_init.3 @@ -101,4 +101,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/posix_spawnattr_getflags.3 b/lib/libc/gen/posix_spawnattr_getflags.3 index b5995ce..2571f4a 100644 --- a/lib/libc/gen/posix_spawnattr_getflags.3 +++ b/lib/libc/gen/posix_spawnattr_getflags.3 @@ -108,4 +108,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/posix_spawnattr_getpgroup.3 b/lib/libc/gen/posix_spawnattr_getpgroup.3 index 91b3e5c..cfc1b54 100644 --- a/lib/libc/gen/posix_spawnattr_getpgroup.3 +++ b/lib/libc/gen/posix_spawnattr_getpgroup.3 @@ -93,4 +93,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/posix_spawnattr_getschedparam.3 b/lib/libc/gen/posix_spawnattr_getschedparam.3 index a137200..5eef96e 100644 --- a/lib/libc/gen/posix_spawnattr_getschedparam.3 +++ b/lib/libc/gen/posix_spawnattr_getschedparam.3 @@ -97,4 +97,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/posix_spawnattr_getschedpolicy.3 b/lib/libc/gen/posix_spawnattr_getschedpolicy.3 index 3e79d4b..5276de5 100644 --- a/lib/libc/gen/posix_spawnattr_getschedpolicy.3 +++ b/lib/libc/gen/posix_spawnattr_getschedpolicy.3 @@ -95,4 +95,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/posix_spawnattr_getsigdefault.3 b/lib/libc/gen/posix_spawnattr_getsigdefault.3 index 8878332..a81c714 100644 --- a/lib/libc/gen/posix_spawnattr_getsigdefault.3 +++ b/lib/libc/gen/posix_spawnattr_getsigdefault.3 @@ -95,4 +95,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/posix_spawnattr_getsigmask.3 b/lib/libc/gen/posix_spawnattr_getsigmask.3 index 4f9c014..be15d9d 100644 --- a/lib/libc/gen/posix_spawnattr_getsigmask.3 +++ b/lib/libc/gen/posix_spawnattr_getsigmask.3 @@ -95,4 +95,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/posix_spawnattr_init.3 b/lib/libc/gen/posix_spawnattr_init.3 index 388fe5a..b4ec52c 100644 --- a/lib/libc/gen/posix_spawnattr_init.3 +++ b/lib/libc/gen/posix_spawnattr_init.3 @@ -120,4 +120,4 @@ and functions first appeared in .Fx 8.0 . .Sh AUTHORS -.An Ed Schouten Aq Mt ed@FreeBSD.org +.An \&Ed Schouten Aq Mt ed@FreeBSD.org diff --git a/lib/libc/gen/raise.c b/lib/libc/gen/raise.c index b3d0aae..994fea5 100644 --- a/lib/libc/gen/raise.c +++ b/lib/libc/gen/raise.c @@ -36,11 +36,17 @@ __FBSDID("$FreeBSD$"); #include <signal.h> #include <unistd.h> +#include "libc_private.h" + __weak_reference(__raise, raise); __weak_reference(__raise, _raise); int __raise(int s) { - return(kill(getpid(), s)); + long id; + + if (__sys_thr_self(&id) == -1) + return (-1); + return (__sys_thr_kill(id, s)); } diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c index 69f59d1..c6f5d3f 100644 --- a/lib/libc/gen/readdir.c +++ b/lib/libc/gen/readdir.c @@ -54,19 +54,25 @@ _readdir_unlocked(dirp, skip) int skip; { struct dirent *dp; + long initial_seek; + long initial_loc = 0; for (;;) { if (dirp->dd_loc >= dirp->dd_size) { if (dirp->dd_flags & __DTF_READALL) return (NULL); + initial_loc = dirp->dd_loc; + dirp->dd_flags &= ~__DTF_SKIPREAD; dirp->dd_loc = 0; } if (dirp->dd_loc == 0 && !(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) { + initial_seek = dirp->dd_seek; dirp->dd_size = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); if (dirp->dd_size <= 0) return (NULL); + _fixtelldir(dirp, initial_seek, initial_loc); } dirp->dd_flags &= ~__DTF_SKIPREAD; dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc); diff --git a/lib/libc/gen/rewinddir.c b/lib/libc/gen/rewinddir.c index 193f4b0..e157cd6 100644 --- a/lib/libc/gen/rewinddir.c +++ b/lib/libc/gen/rewinddir.c @@ -51,6 +51,7 @@ rewinddir(dirp) if (__isthreaded) _pthread_mutex_lock(&dirp->dd_lock); + dirp->dd_flags &= ~__DTF_SKIPREAD; /* current contents are invalid */ if (dirp->dd_flags & __DTF_READALL) _filldir(dirp, false); else { diff --git a/lib/libc/gen/scandir.3 b/lib/libc/gen/scandir.3 index eaba754..aa8dea0 100644 --- a/lib/libc/gen/scandir.3 +++ b/lib/libc/gen/scandir.3 @@ -92,7 +92,7 @@ by freeing each pointer in the array and then the array itself. .Pp The .Fn scandir_b -function behaves in the same way as +function behaves in the same way as .Fn scandir , but takes blocks as arguments instead of function pointers and calls .Fn qsort_b @@ -106,8 +106,8 @@ cannot allocate enough memory to hold all the data structures. .Xr directory 3 , .Xr malloc 3 , .Xr qsort 3 , -.Xr dir 5 , -.Xr strcoll 3 +.Xr strcoll 3 , +.Xr dir 5 .Sh HISTORY The .Fn scandir diff --git a/lib/libc/gen/sem_new.c b/lib/libc/gen/sem_new.c index 3ee0272..c5dc7e7 100644 --- a/lib/libc/gen/sem_new.c +++ b/lib/libc/gen/sem_new.c @@ -439,8 +439,10 @@ _sem_post(sem_t *sem) do { count = sem->_kern._count; - if (USEM_COUNT(count) + 1 > SEM_VALUE_MAX) - return (EOVERFLOW); + if (USEM_COUNT(count) + 1 > SEM_VALUE_MAX) { + errno = EOVERFLOW; + return (-1); + } } while (!atomic_cmpset_rel_int(&sem->_kern._count, count, count + 1)); if (count & USEM_HAS_WAITERS) usem_wake(&sem->_kern); diff --git a/lib/libc/gen/sem_post.3 b/lib/libc/gen/sem_post.3 index 485d2fc..dea8eb6 100644 --- a/lib/libc/gen/sem_post.3 +++ b/lib/libc/gen/sem_post.3 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 15, 2000 +.Dd January 28, 2015 .Dt SEM_POST 3 .Os .Sh NAME @@ -65,6 +65,9 @@ The .Fa sem argument points to an invalid semaphore. +.It Bq Er EOVERFLOW +The semaphore value would exceed +.Dv SEM_VALUE_MAX . .El .Sh SEE ALSO .Xr sem_getvalue 3 , diff --git a/lib/libc/gen/setmode.3 b/lib/libc/gen/setmode.3 index 5cab44a..684c2e1 100644 --- a/lib/libc/gen/setmode.3 +++ b/lib/libc/gen/setmode.3 @@ -28,7 +28,7 @@ .\" @(#)setmode.3 8.2 (Berkeley) 4/28/95 .\" $FreeBSD$ .\" -.Dd April 28, 1995 +.Dd February 22, 2015 .Dt SETMODE 3 .Os .Sh NAME @@ -99,7 +99,20 @@ The function may fail and set errno for any of the errors specified for the library routine -.Xr malloc 3 . +.Xr malloc 3 +or +.Xr strtol 3 . +In addition, +.Fn setmode +will fail and set +.Va errno +to: +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Fa mode +argument does not represent a valid mode. +.El .Sh SEE ALSO .Xr chmod 1 , .Xr stat 2 , diff --git a/lib/libc/gen/setmode.c b/lib/libc/gen/setmode.c index 3966fd0..815cf14 100644 --- a/lib/libc/gen/setmode.c +++ b/lib/libc/gen/setmode.c @@ -39,8 +39,11 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" #include <sys/types.h> #include <sys/stat.h> +#include <sys/sysctl.h> #include <ctype.h> +#include <errno.h> +#include <limits.h> #include <signal.h> #include <stddef.h> #include <stdlib.h> @@ -66,7 +69,8 @@ typedef struct bitcmd { #define CMD2_OBITS 0x08 #define CMD2_UBITS 0x10 -static BITCMD *addcmd(BITCMD *, int, int, int, u_int); +static mode_t getumask(void); +static BITCMD *addcmd(BITCMD *, mode_t, mode_t, mode_t, mode_t); static void compress_mode(BITCMD *); #ifdef SETMODE_DEBUG static void dumpmode(BITCMD *); @@ -151,45 +155,37 @@ common: if (set->cmd2 & CMD2_CLR) { BITCMD *newset; \ setlen += SET_LEN_INCR; \ newset = realloc(saveset, sizeof(BITCMD) * setlen); \ - if (!newset) { \ - if (saveset) \ - free(saveset); \ - saveset = NULL; \ - return (NULL); \ - } \ + if (newset == NULL) \ + goto out; \ set = newset + (set - saveset); \ saveset = newset; \ endset = newset + (setlen - 2); \ } \ - set = addcmd(set, (a), (b), (c), (d)) + set = addcmd(set, (mode_t)(a), (mode_t)(b), (mode_t)(c), (d)) #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) void * setmode(const char *p) { - int perm, who; + int serrno; char op, *ep; BITCMD *set, *saveset, *endset; - sigset_t sigset, sigoset; - mode_t mask; - int equalopdone=0, permXbits, setlen; + mode_t mask, perm, permXbits, who; long perml; + int equalopdone; + int setlen; - if (!*p) + if (!*p) { + errno = EINVAL; return (NULL); + } /* * Get a copy of the mask for the permissions that are mask relative. - * Flip the bits, we want what's not set. Since it's possible that - * the caller is opening files inside a signal handler, protect them - * as best we can. + * Flip the bits, we want what's not set. */ - sigfillset(&sigset); - (void)_sigprocmask(SIG_BLOCK, &sigset, &sigoset); - (void)umask(mask = umask(0)); - mask = ~mask; - (void)_sigprocmask(SIG_SETMASK, &sigoset, NULL); + mask = ~getumask(); setlen = SET_LEN + 2; @@ -203,10 +199,17 @@ setmode(const char *p) * or illegal bits. */ if (isdigit((unsigned char)*p)) { + errno = 0; perml = strtol(p, &ep, 8); - if (*ep || perml < 0 || perml & ~(STANDARD_BITS|S_ISTXT)) { - free(saveset); - return (NULL); + if (*ep) { + errno = EINVAL; + goto out; + } + if (errno == ERANGE && (perml == LONG_MAX || perml == LONG_MIN)) + goto out; + if (perml & ~(STANDARD_BITS|S_ISTXT)) { + errno = EINVAL; + goto out; } perm = (mode_t)perml; ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask); @@ -218,6 +221,7 @@ setmode(const char *p) * Build list of structures to set/clear/copy bits as described by * each clause of the symbolic mode. */ + equalopdone = 0; for (;;) { /* First, find out which bits might be modified. */ for (who = 0;; ++p) { @@ -240,8 +244,8 @@ setmode(const char *p) } getop: if ((op = *p++) != '+' && op != '-' && op != '=') { - free(saveset); - return (NULL); + errno = EINVAL; + goto out; } if (op == '=') equalopdone = 0; @@ -330,10 +334,44 @@ apply: if (!*p) dumpmode(saveset); #endif return (saveset); +out: + serrno = errno; + free(saveset); + errno = serrno; + return NULL; +} + +static mode_t +getumask(void) +{ + sigset_t sigset, sigoset; + size_t len; + mode_t mask; + u_short smask; + + /* + * First try requesting the umask without temporarily modifying it. + * Note that this does not work if the sysctl + * security.bsd.unprivileged_proc_debug is set to 0. + */ + len = sizeof(smask); + if (sysctl((int[4]){ CTL_KERN, KERN_PROC, KERN_PROC_UMASK, getpid() }, + 4, &smask, &len, NULL, 0) == 0) + return (smask); + + /* + * Since it's possible that the caller is opening files inside a signal + * handler, protect them as best we can. + */ + sigfillset(&sigset); + (void)_sigprocmask(SIG_BLOCK, &sigset, &sigoset); + (void)umask(mask = umask(0)); + (void)_sigprocmask(SIG_SETMASK, &sigoset, NULL); + return (mask); } static BITCMD * -addcmd(BITCMD *set, int op, int who, int oparg, u_int mask) +addcmd(BITCMD *set, mode_t op, mode_t who, mode_t oparg, mode_t mask) { switch (op) { case '=': diff --git a/lib/libc/gen/setproctitle.c b/lib/libc/gen/setproctitle.c index cd705fb..9dff328 100644 --- a/lib/libc/gen/setproctitle.c +++ b/lib/libc/gen/setproctitle.c @@ -42,9 +42,10 @@ __FBSDID("$FreeBSD$"); * 1: old_ps_strings at the very top of the stack. * 2: old_ps_strings at SPARE_USRSPACE below the top of the stack. * 3: ps_strings at the very top of the stack. - * This attempts to support a kernel built in the #2 and #3 era. - */ - + * We only support a kernel providing #3 style ps_strings. + * + * For historical purposes, a definition of the old ps_strings structure + * and location is preserved below: struct old_ps_strings { char *old_ps_argvstr; int old_ps_nargvstr; @@ -53,6 +54,7 @@ struct old_ps_strings { }; #define OLD_PS_STRINGS ((struct old_ps_strings *) \ (USRSTACK - SPARE_USRSPACE - sizeof(struct old_ps_strings))) + */ #include <stdarg.h> @@ -136,41 +138,38 @@ setproctitle(const char *fmt, ...) ps_strings = (struct ps_strings *)ul_ps_strings; } - /* PS_STRINGS points to zeroed memory on a style #2 kernel */ - if (ps_strings->ps_argvstr) { - /* style #3 */ - if (oargc == -1) { - /* Record our original args */ - oargc = ps_strings->ps_nargvstr; - oargv = ps_strings->ps_argvstr; - for (i = len = 0; i < oargc; i++) { - /* - * The program may have scribbled into its - * argv array, e.g., to remove some arguments. - * If that has happened, break out before - * trying to call strlen on a NULL pointer. - */ - if (oargv[i] == NULL) { - oargc = i; - break; - } - snprintf(obuf + len, SPT_BUFSIZE - len, "%s%s", - len ? " " : "", oargv[i]); - if (len) - len++; - len += strlen(oargv[i]); - if (len >= SPT_BUFSIZE) - break; + /* + * PS_STRINGS points to zeroed memory on a style #2 kernel. + * Should not happen. + */ + if (ps_strings->ps_argvstr == NULL) + return; + + /* style #3 */ + if (oargc == -1) { + /* Record our original args */ + oargc = ps_strings->ps_nargvstr; + oargv = ps_strings->ps_argvstr; + for (i = len = 0; i < oargc; i++) { + /* + * The program may have scribbled into its + * argv array, e.g., to remove some arguments. + * If that has happened, break out before + * trying to call strlen on a NULL pointer. + */ + if (oargv[i] == NULL) { + oargc = i; + break; } + snprintf(obuf + len, SPT_BUFSIZE - len, "%s%s", + len != 0 ? " " : "", oargv[i]); + if (len != 0) + len++; + len += strlen(oargv[i]); + if (len >= SPT_BUFSIZE) + break; } - ps_strings->ps_nargvstr = nargc; - ps_strings->ps_argvstr = nargvp; - } else { - /* style #2 - we can only restore our first arg :-( */ - if (*obuf == '\0') - strncpy(obuf, OLD_PS_STRINGS->old_ps_argvstr, - SPT_BUFSIZE - 1); - OLD_PS_STRINGS->old_ps_nargvstr = 1; - OLD_PS_STRINGS->old_ps_argvstr = nargvp[0]; } + ps_strings->ps_nargvstr = nargc; + ps_strings->ps_argvstr = nargvp; } diff --git a/lib/libc/gen/sleep.3 b/lib/libc/gen/sleep.3 index ecfa237..00e8f8d 100644 --- a/lib/libc/gen/sleep.3 +++ b/lib/libc/gen/sleep.3 @@ -33,7 +33,7 @@ .Os .Sh NAME .Nm sleep -.Nd suspend process execution for an interval measured in seconds +.Nd suspend thread execution for an interval measured in seconds .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -43,11 +43,11 @@ .Sh DESCRIPTION The .Fn sleep -function suspends execution of the calling process until either +function suspends execution of the calling thread until either .Fa seconds -seconds have elapsed or a signal is delivered to the process and its +seconds have elapsed or a signal is delivered to the thread and its action is to invoke a signal-catching function or to terminate the -process. +thread or process. System activity may lengthen the sleep by an indeterminate amount. .Pp This function is implemented using diff --git a/lib/libc/gen/sleep.c b/lib/libc/gen/sleep.c index b807c2d..6bb4ecd 100644 --- a/lib/libc/gen/sleep.c +++ b/lib/libc/gen/sleep.c @@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include "un-namespace.h" +#include "libc_private.h" + unsigned int __sleep(unsigned int seconds) { @@ -55,12 +57,14 @@ __sleep(unsigned int seconds) time_to_sleep.tv_sec = seconds; time_to_sleep.tv_nsec = 0; - if (_nanosleep(&time_to_sleep, &time_remaining) != -1) + if (((int (*)(const struct timespec *, struct timespec *)) + __libc_interposing[INTERPOS_nanosleep])( + &time_to_sleep, &time_remaining) != -1) return (0); if (errno != EINTR) return (seconds); /* best guess */ return (time_remaining.tv_sec + - (time_remaining.tv_nsec != 0)); /* round up */ + (time_remaining.tv_nsec != 0)); /* round up */ } __weak_reference(__sleep, sleep); diff --git a/lib/libc/gen/stringlist.c b/lib/libc/gen/stringlist.c index a09a8e7..236af17 100644 --- a/lib/libc/gen/stringlist.c +++ b/lib/libc/gen/stringlist.c @@ -10,8 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED diff --git a/lib/libc/gen/swapcontext.c b/lib/libc/gen/swapcontext.c deleted file mode 100644 index c34cb23..0000000 --- a/lib/libc/gen/swapcontext.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2001 Daniel M. Eischen <deischen@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Neither the name of the author nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/signal.h> -#include <sys/ucontext.h> - -#include <errno.h> -#include <stddef.h> - -__weak_reference(__swapcontext, swapcontext); - -int -__swapcontext(ucontext_t *oucp, const ucontext_t *ucp) -{ - int ret; - - if ((oucp == NULL) || (ucp == NULL)) { - errno = EINVAL; - return (-1); - } - oucp->uc_flags &= ~UCF_SWAPPED; - ret = getcontext(oucp); - if ((ret == 0) && !(oucp->uc_flags & UCF_SWAPPED)) { - oucp->uc_flags |= UCF_SWAPPED; - ret = setcontext(ucp); - } - return (ret); -} diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c index 3a5cafe..003f24d 100644 --- a/lib/libc/gen/syslog.c +++ b/lib/libc/gen/syslog.c @@ -261,26 +261,45 @@ vsyslog(int pri, const char *fmt, va_list ap) connectlog(); /* - * If the send() failed, there are two likely scenarios: + * If the send() fails, there are two likely scenarios: * 1) syslogd was restarted * 2) /var/run/log is out of socket buffer space, which * in most cases means local DoS. - * We attempt to reconnect to /var/run/log[priv] to take care of - * case #1 and keep send()ing data to cover case #2 - * to give syslogd a chance to empty its socket buffer. + * If the error does not indicate a full buffer, we address + * case #1 by attempting to reconnect to /var/run/log[priv] + * and resending the message once. * - * If we are working with a priveleged socket, then take - * only one attempt, because we don't want to freeze a + * If we are working with a privileged socket, the retry + * attempts end there, because we don't want to freeze a * critical application like su(1) or sshd(8). * + * Otherwise, we address case #2 by repeatedly retrying the + * send() to give syslogd a chance to empty its socket buffer. */ if (send(LogFile, tbuf, cnt, 0) < 0) { if (errno != ENOBUFS) { + /* + * Scenario 1: syslogd was restarted + * reconnect and resend once + */ disconnectlog(); connectlog(); + if (send(LogFile, tbuf, cnt, 0) >= 0) { + THREAD_UNLOCK(); + return; + } + /* + * if the resend failed, fall through to + * possible scenario 2 + */ } - do { + while (errno == ENOBUFS) { + /* + * Scenario 2: out of socket buffer space + * possible DoS, fail fast on a privileged + * socket + */ if (status == CONNPRIV) break; _usleep(1); @@ -288,7 +307,7 @@ vsyslog(int pri, const char *fmt, va_list ap) THREAD_UNLOCK(); return; } - } while (errno == ENOBUFS); + } } else { THREAD_UNLOCK(); return; @@ -350,7 +369,7 @@ connectlog(void) SyslogAddr.sun_family = AF_UNIX; /* - * First try priveleged socket. If no success, + * First try privileged socket. If no success, * then try default socket. */ (void)strncpy(SyslogAddr.sun_path, _PATH_LOG_PRIV, diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c index d72b500..19cd6ee 100644 --- a/lib/libc/gen/telldir.c +++ b/lib/libc/gen/telldir.c @@ -101,9 +101,22 @@ _seekdir(dirp, loc) return; if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek) return; + + /* If it's within the same chunk of data, don't bother reloading. */ + if (lp->loc_seek == dirp->dd_seek) { + /* + * If we go back to 0 don't make the next readdir + * trigger a call to getdirentries(). + */ + if (lp->loc_loc == 0) + dirp->dd_flags |= __DTF_SKIPREAD; + dirp->dd_loc = lp->loc_loc; + return; + } (void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET); dirp->dd_seek = lp->loc_seek; dirp->dd_loc = 0; + dirp->dd_flags &= ~__DTF_SKIPREAD; /* current contents are invalid */ while (dirp->dd_loc < lp->loc_loc) { dp = _readdir_unlocked(dirp, 0); if (dp == NULL) @@ -112,6 +125,30 @@ _seekdir(dirp, loc) } /* + * After readdir returns the last entry in a block, a call to telldir + * returns a location that is after the end of that last entry. + * However, that location doesn't refer to a valid directory entry. + * Ideally, the call to telldir would return a location that refers to + * the first entry in the next block. That location is not known + * until the next block is read, so readdir calls this function after + * fetching a new block to fix any such telldir locations. + */ +void +_fixtelldir(DIR *dirp, long oldseek, long oldloc) +{ + struct ddloc *lp; + + lp = LIST_FIRST(&dirp->dd_td->td_locq); + if (lp != NULL) { + if (lp->loc_loc == oldloc && + lp->loc_seek == oldseek) { + lp->loc_seek = dirp->dd_seek; + lp->loc_loc = dirp->dd_loc; + } + } +} + +/* * Reclaim memory for telldir cookies which weren't used. */ void diff --git a/lib/libc/gen/telldir.h b/lib/libc/gen/telldir.h index 04989bb..bccabb1 100644 --- a/lib/libc/gen/telldir.h +++ b/lib/libc/gen/telldir.h @@ -64,5 +64,6 @@ bool _filldir(DIR *, bool); struct dirent *_readdir_unlocked(DIR *, int); void _reclaim_telldir(DIR *); void _seekdir(DIR *, long); +void _fixtelldir(DIR *dirp, long oldseek, long oldloc); #endif diff --git a/lib/libc/gen/termios.c b/lib/libc/gen/termios.c index 7e9f169..f8b7354 100644 --- a/lib/libc/gen/termios.c +++ b/lib/libc/gen/termios.c @@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include "un-namespace.h" +#include "libc_private.h" + int tcgetattr(int fd, struct termios *t) { @@ -208,13 +210,23 @@ tcsendbreak(int fd, int len __unused) } int -__tcdrain(int fd) +__libc_tcdrain(int fd) { + return (_ioctl(fd, TIOCDRAIN, 0)); } -__weak_reference(__tcdrain, tcdrain); -__weak_reference(__tcdrain, _tcdrain); +#pragma weak tcdrain +int +tcdrain(int fd) +{ + + return (((int (*)(int)) + __libc_interposing[INTERPOS_tcdrain])(fd)); +} + +__weak_reference(__libc_tcdrain, __tcdrain); +__weak_reference(__libc_tcdrain, _tcdrain); int tcflush(int fd, int which) diff --git a/lib/libc/gen/tls.c b/lib/libc/gen/tls.c index 5219418..58ebb55 100644 --- a/lib/libc/gen/tls.c +++ b/lib/libc/gen/tls.c @@ -65,13 +65,14 @@ void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign); #if defined(__amd64__) #define TLS_TCB_ALIGN 16 #elif defined(__powerpc__) || defined(__i386__) || defined(__arm__) || \ - defined(__sparc64__) || defined(__mips__) + defined(__sparc64__) || defined(__mips__) || defined(__aarch64__) #define TLS_TCB_ALIGN sizeof(void *) #else #error TLS_TCB_ALIGN undefined for target architecture #endif -#if defined(__arm__) || defined(__mips__) || defined(__powerpc__) +#if defined(__arm__) || defined(__mips__) || defined(__powerpc__) || \ + defined(__aarch64__) #define TLS_VARIANT_I #endif #if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) diff --git a/lib/libc/gen/trivial-getcontextx.c b/lib/libc/gen/trivial-getcontextx.c new file mode 100644 index 0000000..54f8513 --- /dev/null +++ b/lib/libc/gen/trivial-getcontextx.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/ucontext.h> +#include <errno.h> +#include <stdlib.h> + +int +__getcontextx_size(void) +{ + + return (sizeof(ucontext_t)); +} + +int +__fillcontextx2(char *ctx) +{ + + return (0); +} + +int +__fillcontextx(char *ctx) +{ + ucontext_t *ucp; + + ucp = (ucontext_t *)ctx; + return (getcontext(ucp)); +} + +__weak_reference(__getcontextx, getcontextx); + +ucontext_t * +__getcontextx(void) +{ + char *ctx; + int error; + + ctx = malloc(__getcontextx_size()); + if (ctx == NULL) + return (NULL); + if (__fillcontextx(ctx) == -1) { + error = errno; + free(ctx); + errno = error; + return (NULL); + } + return ((ucontext_t *)ctx); +} diff --git a/lib/libc/gen/ttyname.c b/lib/libc/gen/ttyname.c index a21b77f..02aa158 100644 --- a/lib/libc/gen/ttyname.c +++ b/lib/libc/gen/ttyname.c @@ -65,7 +65,7 @@ ttyname_r(int fd, char *buf, size_t len) /* Must be a terminal. */ if (!isatty(fd)) - return (ENOTTY); + return (errno); /* Must have enough room */ if (len <= sizeof(_PATH_DEV)) return (ERANGE); @@ -73,7 +73,7 @@ ttyname_r(int fd, char *buf, size_t len) strcpy(buf, _PATH_DEV); used = strlen(buf); if (fdevname_r(fd, buf + used, len - used) == NULL) - return (ENOTTY); + return (errno == EINVAL ? ERANGE : errno); return (0); } diff --git a/lib/libc/gen/ulimit.c b/lib/libc/gen/ulimit.c index e1bc020..2c090c0 100644 --- a/lib/libc/gen/ulimit.c +++ b/lib/libc/gen/ulimit.c @@ -40,7 +40,7 @@ ulimit(int cmd, ...) { struct rlimit limit; va_list ap; - long arg; + rlim_t arg; if (cmd == UL_GETFSIZE) { if (getrlimit(RLIMIT_FSIZE, &limit) == -1) @@ -53,14 +53,16 @@ ulimit(int cmd, ...) va_start(ap, cmd); arg = va_arg(ap, long); va_end(ap); - limit.rlim_max = limit.rlim_cur = (rlim_t)arg * 512; + if (arg < 0) + arg = LONG_MAX; + if (arg > RLIM_INFINITY / 512) + arg = RLIM_INFINITY / 512; + limit.rlim_max = limit.rlim_cur = arg * 512; /* The setrlimit() function sets errno to EPERM if needed. */ if (setrlimit(RLIMIT_FSIZE, &limit) == -1) return (-1); - if (arg * 512 > LONG_MAX) - return (LONG_MAX); - return (arg); + return ((long)arg); } else { errno = EINVAL; return (-1); diff --git a/lib/libc/gen/usleep.c b/lib/libc/gen/usleep.c index 7d6559b..7c35f6c 100644 --- a/lib/libc/gen/usleep.c +++ b/lib/libc/gen/usleep.c @@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include "un-namespace.h" +#include "libc_private.h" + int __usleep(useconds_t useconds) { @@ -45,7 +47,8 @@ __usleep(useconds_t useconds) time_to_sleep.tv_nsec = (useconds % 1000000) * 1000; time_to_sleep.tv_sec = useconds / 1000000; - return (_nanosleep(&time_to_sleep, NULL)); + return (((int (*)(const struct timespec *, struct timespec *)) + __libc_interposing[INTERPOS_nanosleep])(&time_to_sleep, NULL)); } __weak_reference(__usleep, usleep); diff --git a/lib/libc/gen/wait.c b/lib/libc/gen/wait.c index 2169b9d..46a3fdd 100644 --- a/lib/libc/gen/wait.c +++ b/lib/libc/gen/wait.c @@ -40,10 +40,14 @@ __FBSDID("$FreeBSD$"); #include <sys/resource.h> #include "un-namespace.h" +#include "libc_private.h" + pid_t __wait(int *istat) { - return (_wait4(WAIT_ANY, istat, 0, (struct rusage *)0)); + + return (((pid_t (*)(pid_t, int *, int, struct rusage *)) + __libc_interposing[INTERPOS_wait4])(WAIT_ANY, istat, 0, NULL)); } __weak_reference(__wait, wait); diff --git a/lib/libc/gen/wait3.c b/lib/libc/gen/wait3.c index 6098773..965effe 100644 --- a/lib/libc/gen/wait3.c +++ b/lib/libc/gen/wait3.c @@ -40,11 +40,14 @@ __FBSDID("$FreeBSD$"); #include <sys/resource.h> #include "un-namespace.h" +#include "libc_private.h" + pid_t -wait3(istat, options, rup) - int *istat; - int options; - struct rusage *rup; +__wait3(int *istat, int options, struct rusage *rup) { - return (_wait4(WAIT_ANY, istat, options, rup)); + + return (((pid_t (*)(pid_t, int *, int, struct rusage *)) + __libc_interposing[INTERPOS_wait4])(WAIT_ANY, istat, options, rup)); } + +__weak_reference(__wait3, wait3); diff --git a/lib/libc/gen/waitid.c b/lib/libc/gen/waitid.c index 795b208..17a2dd6 100644 --- a/lib/libc/gen/waitid.c +++ b/lib/libc/gen/waitid.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <signal.h> #include <errno.h> #include "un-namespace.h" +#include "libc_private.h" int __waitid(idtype_t idtype, id_t id, siginfo_t *info, int flags) @@ -44,7 +45,9 @@ __waitid(idtype_t idtype, id_t id, siginfo_t *info, int flags) int status; pid_t ret; - ret = _wait6(idtype, id, &status, flags, NULL, info); + ret = ((pid_t (*)(idtype_t, id_t, int *, int, struct __wrusage *, + siginfo_t *))__libc_interposing[INTERPOS_wait6])(idtype, id, + &status, flags, NULL, info); /* * According to SUSv4, waitid() shall not return a PID when a diff --git a/lib/libc/gen/waitpid.c b/lib/libc/gen/waitpid.c index b001837..5177591 100644 --- a/lib/libc/gen/waitpid.c +++ b/lib/libc/gen/waitpid.c @@ -40,10 +40,14 @@ __FBSDID("$FreeBSD$"); #include <sys/resource.h> #include "un-namespace.h" +#include "libc_private.h" + pid_t __waitpid(pid_t pid, int *istat, int options) { - return (_wait4(pid, istat, options, (struct rusage *)0)); + + return (((pid_t (*)(pid_t, int *, int, struct rusage *)) + __libc_interposing[INTERPOS_wait4])(pid, istat, options, NULL)); } __weak_reference(__waitpid, waitpid); diff --git a/lib/libc/gen/wordexp.c b/lib/libc/gen/wordexp.c index 377caff..c7f4b1d 100644 --- a/lib/libc/gen/wordexp.c +++ b/lib/libc/gen/wordexp.c @@ -118,8 +118,10 @@ we_askshell(const char *words, wordexp_t *we, int flags) char *nstrings; /* Temporary for realloc() */ char **nwv; /* Temporary for realloc() */ sigset_t newsigblock, oldsigblock; + const char *ifs; serrno = errno; + ifs = getenv("IFS"); if (pipe2(pdes, O_CLOEXEC) < 0) return (WRDE_NOSPACE); /* XXX */ @@ -145,7 +147,8 @@ we_askshell(const char *words, wordexp_t *we, int flags) _fcntl(pdes[1], F_SETFD, 0)) < 0) _exit(1); execl(_PATH_BSHELL, "sh", flags & WRDE_UNDEF ? "-u" : "+u", - "-c", "eval \"$1\";eval \"wordexp $2\"", "", + "-c", "IFS=$1;eval \"$2\";eval \"wordexp $3\"", "", + ifs != NULL ? ifs : " \t\n", flags & WRDE_SHOWERR ? "" : "exec 2>/dev/null", words, (char *)NULL); _exit(1); |