diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/gen/fnmatch.c | 77 | ||||
-rw-r--r-- | lib/libc/gen/wordexp.3 | 33 | ||||
-rw-r--r-- | lib/libc/gen/wordexp.c | 220 | ||||
-rw-r--r-- | lib/libc/sys/ptrace.2 | 25 | ||||
-rw-r--r-- | lib/libcam/camlib.c | 4 | ||||
-rw-r--r-- | lib/libdpv/dpv.3 | 6 | ||||
-rw-r--r-- | lib/libfigpar/figpar.3 | 6 | ||||
-rw-r--r-- | lib/libmagic/config.h | 6 | ||||
-rw-r--r-- | lib/libthr/arch/amd64/Makefile.inc | 6 | ||||
-rw-r--r-- | lib/libthr/arch/i386/Makefile.inc | 6 |
10 files changed, 257 insertions, 132 deletions
diff --git a/lib/libc/gen/fnmatch.c b/lib/libc/gen/fnmatch.c index 47d0a41..db0bf89 100644 --- a/lib/libc/gen/fnmatch.c +++ b/lib/libc/gen/fnmatch.c @@ -91,11 +91,14 @@ fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs) int flags; mbstate_t patmbs, strmbs; { + const char *bt_pattern, *bt_string; + mbstate_t bt_patmbs, bt_strmbs; char *newp; char c; wchar_t pc, sc; size_t pclen, sclen; + bt_pattern = bt_string = NULL; for (;;) { pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs); if (pclen == (size_t)-1 || pclen == (size_t)-2) @@ -111,16 +114,18 @@ fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs) case EOS: if ((flags & FNM_LEADING_DIR) && sc == '/') return (0); - return (sc == EOS ? 0 : FNM_NOMATCH); + if (sc == EOS) + return (0); + goto backtrack; case '?': if (sc == EOS) return (FNM_NOMATCH); if (sc == '/' && (flags & FNM_PATHNAME)) - return (FNM_NOMATCH); + goto backtrack; if (sc == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - return (FNM_NOMATCH); + goto backtrack; string += sclen; break; case '*': @@ -132,7 +137,7 @@ fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs) if (sc == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - return (FNM_NOMATCH); + goto backtrack; /* Optimize for pattern with * at end or before /. */ if (c == EOS) @@ -148,33 +153,24 @@ fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs) break; } - /* General case, use recursion. */ - while (sc != EOS) { - if (!fnmatch1(pattern, string, stringstart, - flags, patmbs, strmbs)) - return (0); - sclen = mbrtowc(&sc, string, MB_LEN_MAX, - &strmbs); - if (sclen == (size_t)-1 || - sclen == (size_t)-2) { - sc = (unsigned char)*string; - sclen = 1; - memset(&strmbs, 0, sizeof(strmbs)); - } - if (sc == '/' && flags & FNM_PATHNAME) - break; - string += sclen; - } - return (FNM_NOMATCH); + /* + * First try the shortest match for the '*' that + * could work. We can forget any earlier '*' since + * there is no way having it match more characters + * can help us, given that we are already here. + */ + bt_pattern = pattern, bt_patmbs = patmbs; + bt_string = string, bt_strmbs = strmbs; + break; case '[': if (sc == EOS) return (FNM_NOMATCH); if (sc == '/' && (flags & FNM_PATHNAME)) - return (FNM_NOMATCH); + goto backtrack; if (sc == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) - return (FNM_NOMATCH); + goto backtrack; switch (rangematch(pattern, sc, flags, &newp, &patmbs)) { @@ -184,7 +180,7 @@ fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs) pattern = newp; break; case RANGE_NOMATCH: - return (FNM_NOMATCH); + goto backtrack; } string += sclen; break; @@ -199,14 +195,39 @@ fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs) /* FALLTHROUGH */ default: norm: + string += sclen; if (pc == sc) ; else if ((flags & FNM_CASEFOLD) && (towlower(pc) == towlower(sc))) ; - else - return (FNM_NOMATCH); - string += sclen; + else { + backtrack: + /* + * If we have a mismatch (other than hitting + * the end of the string), go back to the last + * '*' seen and have it match one additional + * character. + */ + if (bt_pattern == NULL) + return (FNM_NOMATCH); + sclen = mbrtowc(&sc, bt_string, MB_LEN_MAX, + &bt_strmbs); + if (sclen == (size_t)-1 || + sclen == (size_t)-2) { + sc = (unsigned char)*bt_string; + sclen = 1; + memset(&bt_strmbs, 0, + sizeof(bt_strmbs)); + } + if (sc == EOS) + return (FNM_NOMATCH); + if (sc == '/' && flags & FNM_PATHNAME) + return (FNM_NOMATCH); + bt_string += sclen; + pattern = bt_pattern, patmbs = bt_patmbs; + string = bt_string, strmbs = bt_strmbs; + } break; } } diff --git a/lib/libc/gen/wordexp.3 b/lib/libc/gen/wordexp.3 index 02fc253..1f6421d 100644 --- a/lib/libc/gen/wordexp.3 +++ b/lib/libc/gen/wordexp.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 29, 2004 +.Dd September 30, 2015 .Dt WORDEXP 3 .Os .Sh NAME @@ -108,8 +108,8 @@ function frees the memory allocated by .Sh IMPLEMENTATION NOTES The .Fn wordexp -function is implemented as a wrapper around the undocumented -.Ic wordexp +function is implemented using the undocumented +.Ic freebsd_wordexp shell built-in command. .Sh RETURN VALUES The @@ -189,18 +189,19 @@ and functions conform to .St -p1003.1-2001 . .Sh BUGS -Do not pass untrusted user data to -.Fn wordexp , -regardless of whether the -.Dv WRDE_NOCMD -flag is set. -The -.Fn wordexp -function attempts to detect input that would cause commands to be -executed before passing it to the shell -but it does not use the same parser so it may be fooled. -.Pp The current .Fn wordexp -implementation does not recognize multibyte characters, since the -shell (which it invokes to perform expansions) does not. +implementation does not recognize multibyte characters other than UTF-8, since +the shell (which it invokes to perform expansions) does not. +.Sh SECURITY CONSIDERATIONS +Pathname generation may create output that is exponentially larger than the +input size. +.Pp +Although this implementation detects command substitution reliably for +.Dv WRDE_NOCMD , +the attack surface remains fairly large. +Also, some other implementations +(such as older versions of this one) +may execute command substitutions even if +.Dv WRDE_NOCMD +is set. diff --git a/lib/libc/gen/wordexp.c b/lib/libc/gen/wordexp.c index 329044d..fe57a48 100644 --- a/lib/libc/gen/wordexp.c +++ b/lib/libc/gen/wordexp.c @@ -32,6 +32,7 @@ #include <fcntl.h> #include <paths.h> #include <signal.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -43,7 +44,7 @@ __FBSDID("$FreeBSD$"); static int we_askshell(const char *, wordexp_t *, int); -static int we_check(const char *, int); +static int we_check(const char *); /* * wordexp -- @@ -65,7 +66,7 @@ wordexp(const char * __restrict words, wordexp_t * __restrict we, int flags) we->we_strings = NULL; we->we_nbytes = 0; } - if ((error = we_check(words, flags)) != 0) { + if ((error = we_check(words)) != 0) { wordfree(we); return (error); } @@ -94,18 +95,37 @@ we_read_fully(int fd, char *buffer, size_t len) return done; } +static bool +we_write_fully(int fd, const char *buffer, size_t len) +{ + size_t done; + ssize_t nwritten; + + done = 0; + do { + nwritten = _write(fd, buffer + done, len - done); + if (nwritten == -1 && errno == EINTR) + continue; + if (nwritten <= 0) + return (false); + done += nwritten; + } while (done != len); + return (true); +} + /* * we_askshell -- - * Use the `wordexp' /bin/sh builtin function to do most of the work - * in expanding the word string. This function is complicated by + * Use the `freebsd_wordexp' /bin/sh builtin function to do most of the + * work in expanding the word string. This function is complicated by * memory management. */ static int we_askshell(const char *words, wordexp_t *we, int flags) { - int pdes[2]; /* Pipe to child */ - char bbuf[9]; /* Buffer for byte count */ - char wbuf[9]; /* Buffer for word count */ + int pdesw[2]; /* Pipe for writing words */ + int pdes[2]; /* Pipe for reading output */ + char wfdstr[sizeof(int) * 3 + 1]; + char buf[35]; /* Buffer for byte and word count */ long nwords, nbytes; /* Number of words, bytes from child */ long i; /* Handy integer */ size_t sofs; /* Offset into we->we_strings */ @@ -124,13 +144,21 @@ we_askshell(const char *words, wordexp_t *we, int flags) serrno = errno; ifs = getenv("IFS"); - if (pipe2(pdes, O_CLOEXEC) < 0) + if (pipe2(pdesw, O_CLOEXEC) < 0) + return (WRDE_NOSPACE); /* XXX */ + snprintf(wfdstr, sizeof(wfdstr), "%d", pdesw[0]); + if (pipe2(pdes, O_CLOEXEC) < 0) { + _close(pdesw[0]); + _close(pdesw[1]); return (WRDE_NOSPACE); /* XXX */ + } (void)sigemptyset(&newsigblock); (void)sigaddset(&newsigblock, SIGCHLD); (void)__libc_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock); if ((pid = fork()) < 0) { serrno = errno; + _close(pdesw[0]); + _close(pdesw[1]); _close(pdes[0]); _close(pdes[1]); (void)__libc_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); @@ -139,38 +167,63 @@ we_askshell(const char *words, wordexp_t *we, int flags) } else if (pid == 0) { /* - * We are the child; just get /bin/sh to run the wordexp - * builtin on `words'. + * We are the child; make /bin/sh expand `words'. */ (void)__libc_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); if ((pdes[1] != STDOUT_FILENO ? _dup2(pdes[1], STDOUT_FILENO) : _fcntl(pdes[1], F_SETFD, 0)) < 0) _exit(1); + if (_fcntl(pdesw[0], F_SETFD, 0) < 0) + _exit(1); execl(_PATH_BSHELL, "sh", flags & WRDE_UNDEF ? "-u" : "+u", - "-c", "IFS=$1;eval \"$2\";eval \"wordexp $3\"", "", + "-c", "IFS=$1;eval \"$2\";" + "freebsd_wordexp -f \"$3\" ${4:+\"$4\"}", + "", ifs != NULL ? ifs : " \t\n", - flags & WRDE_SHOWERR ? "" : "exec 2>/dev/null", words, + flags & WRDE_SHOWERR ? "" : "exec 2>/dev/null", + wfdstr, + flags & WRDE_NOCMD ? "-p" : "", (char *)NULL); _exit(1); } /* - * We are the parent; read the output of the shell wordexp function, - * which is a 32-bit hexadecimal word count, a 32-bit hexadecimal - * byte count (not including terminating null bytes), followed by - * the expanded words separated by nulls. + * We are the parent; write the words. */ _close(pdes[1]); - if (we_read_fully(pdes[0], wbuf, 8) != 8 || - we_read_fully(pdes[0], bbuf, 8) != 8) { - error = flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX; + _close(pdesw[0]); + if (!we_write_fully(pdesw[1], words, strlen(words))) { + _close(pdesw[1]); + error = WRDE_SYNTAX; + goto cleanup; + } + _close(pdesw[1]); + /* + * Read the output of the shell wordexp function, + * which is a byte indicating that the words were parsed successfully, + * a 64-bit hexadecimal word count, a dummy byte, a 64-bit hexadecimal + * byte count (not including terminating null bytes), followed by the + * expanded words separated by nulls. + */ + switch (we_read_fully(pdes[0], buf, 34)) { + case 1: + error = buf[0] == 'C' ? WRDE_CMDSUB : + flags & WRDE_UNDEF ? WRDE_BADVAL : + WRDE_SYNTAX; + serrno = errno; + goto cleanup; + case 34: + break; + default: + error = WRDE_SYNTAX; serrno = errno; goto cleanup; } - wbuf[8] = bbuf[8] = '\0'; - nwords = strtol(wbuf, NULL, 16); - nbytes = strtol(bbuf, NULL, 16) + nwords; + buf[17] = '\0'; + nwords = strtol(buf + 1, NULL, 16); + buf[34] = '\0'; + nbytes = strtol(buf + 18, NULL, 16) + nwords; /* * Allocate or reallocate (when flags & WRDE_APPEND) the word vector @@ -243,83 +296,96 @@ cleanup: * we_check -- * Check that the string contains none of the following unquoted * special characters: <newline> |&;<>(){} - * or command substitutions when WRDE_NOCMD is set in flags. + * This mainly serves for {} which are normally legal in sh. + * It deliberately does not attempt to model full sh syntax. */ static int -we_check(const char *words, int flags) +we_check(const char *words) { char c; - int dquote, level, quote, squote; + /* Saw \ or $, possibly not special: */ + bool quote = false, dollar = false; + /* Saw ', ", ${, ` or $(, possibly not special: */ + bool have_sq = false, have_dq = false, have_par_begin = false; + bool have_cmd = false; + /* Definitely saw a ', ", ${, ` or $(, need a closing character: */ + bool need_sq = false, need_dq = false, need_par_end = false; + bool need_cmd_old = false, need_cmd_new = false; - quote = squote = dquote = 0; while ((c = *words++) != '\0') { switch (c) { case '\\': - if (squote == 0) - quote ^= 1; + quote = !quote; + continue; + case '$': + if (quote) + quote = false; + else + dollar = !dollar; continue; case '\'': - if (quote + dquote == 0) - squote ^= 1; + if (!quote && !have_sq && !have_dq) + need_sq = true; + else + need_sq = false; + have_sq = true; break; case '"': - if (quote + squote == 0) - dquote ^= 1; + if (!quote && !have_sq && !have_dq) + need_dq = true; + else + need_dq = false; + have_dq = true; break; case '`': - if (quote + squote == 0 && flags & WRDE_NOCMD) - return (WRDE_CMDSUB); - while ((c = *words++) != '\0' && c != '`') - if (c == '\\' && (c = *words++) == '\0') - break; - if (c == '\0') - return (WRDE_SYNTAX); + if (!quote && !have_sq && !have_cmd) + need_cmd_old = true; + else + need_cmd_old = false; + have_cmd = true; break; - case '|': case '&': case ';': case '<': case '>': - case '{': case '}': case '(': case ')': case '\n': - if (quote + squote + dquote == 0) + case '{': + if (!quote && !dollar && !have_sq && !have_dq && + !have_cmd) return (WRDE_BADCHAR); + if (dollar) { + if (!quote && !have_sq) + need_par_end = true; + have_par_begin = true; + } break; - case '$': - if ((c = *words++) == '\0') - break; - else if (quote + squote == 0 && c == '(') { - if (flags & WRDE_NOCMD && *words != '(') - return (WRDE_CMDSUB); - level = 1; - while ((c = *words++) != '\0') { - if (c == '\\') { - if ((c = *words++) == '\0') - break; - } else if (c == '(') - level++; - else if (c == ')' && --level == 0) - break; - } - if (c == '\0' || level != 0) - return (WRDE_SYNTAX); - } else if (quote + squote == 0 && c == '{') { - level = 1; - while ((c = *words++) != '\0') { - if (c == '\\') { - if ((c = *words++) == '\0') - break; - } else if (c == '{') - level++; - else if (c == '}' && --level == 0) - break; - } - if (c == '\0' || level != 0) - return (WRDE_SYNTAX); - } else - --words; + case '}': + if (!quote && !have_sq && !have_dq && !have_par_begin && + !have_cmd) + return (WRDE_BADCHAR); + need_par_end = false; + break; + case '(': + if (!quote && !dollar && !have_sq && !have_dq && + !have_cmd) + return (WRDE_BADCHAR); + if (dollar) { + if (!quote && !have_sq) + need_cmd_new = true; + have_cmd = true; + } + break; + case ')': + if (!quote && !have_sq && !have_dq && !have_cmd) + return (WRDE_BADCHAR); + need_cmd_new = false; + break; + case '|': case '&': case ';': case '<': case '>': case '\n': + if (!quote && !have_sq && !have_dq && !have_cmd) + return (WRDE_BADCHAR); break; default: break; } - quote = 0; + quote = dollar = false; } - if (quote + squote + dquote != 0) + if (quote || dollar || need_sq || need_dq || need_par_end || + need_cmd_old || need_cmd_new) return (WRDE_SYNTAX); return (0); diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2 index 71b432f..5c93438 100644 --- a/lib/libc/sys/ptrace.2 +++ b/lib/libc/sys/ptrace.2 @@ -2,7 +2,7 @@ .\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $ .\" .\" This file is in the public domain. -.Dd July 3, 2015 +.Dd October 6, 2015 .Dt PTRACE 2 .Os .Sh NAME @@ -307,6 +307,8 @@ struct ptrace_lwpinfo { siginfo_t pl_siginfo; char pl_tdname[MAXCOMLEN + 1]; int pl_child_pid; + u_int pl_syscall_code; + u_int pl_syscall_narg; }; .Ed .Pp @@ -395,6 +397,27 @@ stop when .Dv PL_FLAG_FORKED is set in .Va pl_flags . +.It pl_syscall_code +The ABI-specific identifier of the current system call. +Note that for indirect system calls this field reports the indirected +system call. +Only valid when +.Dv PL_FLAG_SCE +or +.Dv PL_FLAG_SCX +is set in +.Va pl_flags. +.It pl_syscall_narg +The number of arguments passed to the current system call not counting +the system call identifier. +Note that for indirect system calls this field reports the arguments +passed to the indirected system call. +Only valid when +.Dv PL_FLAG_SCE +or +.Dv PL_FLAG_SCX +is set in +.Va pl_flags. .El .It PT_GETNUMLWPS This request returns the number of kernel threads associated with the diff --git a/lib/libcam/camlib.c b/lib/libcam/camlib.c index f320247..b7024a6 100644 --- a/lib/libcam/camlib.c +++ b/lib/libcam/camlib.c @@ -676,8 +676,10 @@ cam_close_spec_device(struct cam_device *dev) if (dev == NULL) return; - if (dev->fd >= 0) + if (dev->fd >= 0) { close(dev->fd); + dev->fd = -1; + } } char * diff --git a/lib/libdpv/dpv.3 b/lib/libdpv/dpv.3 index 8c04ac3..4779540 100644 --- a/lib/libdpv/dpv.3 +++ b/lib/libdpv/dpv.3 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2013-2014 Devin Teske +.\" Copyright (c) 2013-2015 Devin Teske .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd Oct 24, 2014 +.Dd Oct 22, 2015 .Dt DPV 3 .Os .Sh NAME @@ -441,7 +441,7 @@ or desired values. The .Nm library first appeared in -.Fx 11.0 . +.Fx 10.2 . .Sh AUTHORS .An Devin Teske Aq dteske@FreeBSD.org .Sh BUGS diff --git a/lib/libfigpar/figpar.3 b/lib/libfigpar/figpar.3 index 549808e..8fd49d3 100644 --- a/lib/libfigpar/figpar.3 +++ b/lib/libfigpar/figpar.3 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2013-2014 Devin Teske <dteske@FreeBSD.org> +.\" Copyright (c) 2013-2015 Devin Teske <dteske@FreeBSD.org> .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd Oct 24, 2014 +.Dd Oct 22, 2015 .Dt FIGPAR 3 .Os .Sh NAME @@ -243,7 +243,7 @@ Convert a string to lower case. The .Nm library first appeared in -.Fx 11.0 . +.Fx 10.2 . .Sh AUTHORS .An Devin Teske Aq dteske@FreeBSD.org .Sh BUGS diff --git a/lib/libmagic/config.h b/lib/libmagic/config.h index 956b040..752b82b 100644 --- a/lib/libmagic/config.h +++ b/lib/libmagic/config.h @@ -290,7 +290,7 @@ #define PACKAGE_NAME "file" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "file 5.23" +#define PACKAGE_STRING "file 5.25" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "file" @@ -299,7 +299,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "5.23" +#define PACKAGE_VERSION "5.25" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 @@ -330,7 +330,7 @@ /* Version number of package */ -#define VERSION "5.23" +#define VERSION "5.25" /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ diff --git a/lib/libthr/arch/amd64/Makefile.inc b/lib/libthr/arch/amd64/Makefile.inc index e6d99ec..0ae764c 100644 --- a/lib/libthr/arch/amd64/Makefile.inc +++ b/lib/libthr/arch/amd64/Makefile.inc @@ -1,3 +1,9 @@ #$FreeBSD$ SRCS+= pthread_md.c _umtx_op_err.S + +# With the current compiler and libthr code, using SSE in libthr +# does not provide enough performance improvement to outweigh +# the extra context switch cost. This can measurably impact +# performance when the application also does not use enough SSE. +CFLAGS+=${CFLAGS_NO_SIMD} diff --git a/lib/libthr/arch/i386/Makefile.inc b/lib/libthr/arch/i386/Makefile.inc index 01290d5..81fb6bb 100644 --- a/lib/libthr/arch/i386/Makefile.inc +++ b/lib/libthr/arch/i386/Makefile.inc @@ -1,3 +1,9 @@ # $FreeBSD$ SRCS+= pthread_md.c _umtx_op_err.S + +# With the current compiler and libthr code, using SSE in libthr +# does not provide enough performance improvement to outweigh +# the extra context switch cost. This can measurably impact +# performance when the application also does not use enough SSE. +CFLAGS+=${CFLAGS_NO_SIMD} |