diff options
author | Dan McDonald <danmcd@joyent.com> | 2022-01-18 13:30:10 -0500 |
---|---|---|
committer | Dan McDonald <danmcd@joyent.com> | 2022-01-18 13:30:10 -0500 |
commit | daf61a2ba69d236f9da41f1a991cf8af3f3ff72c (patch) | |
tree | f63cff2bcde5511605ed4466f719e2a7ccb54087 /usr/src | |
parent | 561a2476a800c02bf5a1e7720002e17699fcaf27 (diff) | |
parent | f859e7171bb5db34321e45585839c6c3200ebb90 (diff) | |
download | illumos-joyent-daf61a2ba69d236f9da41f1a991cf8af3f3ff72c.tar.gz |
[illumos-gate merge]
commit f859e7171bb5db34321e45585839c6c3200ebb90
14424 tmpfs can be induced to deadlock
commit d278f1c9d93ca9beb430b23636bc2a848535e0e0
14350 uath: mismatched bound
commit 53496f229747a02889ac4f8518b2e4b44ff2f9e0
14349 libcrypt: mismatched bound
commit dc1259b65efc626c37cd057774d3e3393e84c33c
14328 cscope-fast: this 'if' clause does not guard...
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/libcrypt/common/cryptio.c | 12 | ||||
-rw-r--r-- | usr/src/tools/cscope-fast/cgrep.c | 29 | ||||
-rw-r--r-- | usr/src/uts/common/fs/tmpfs/tmp_dir.c | 66 | ||||
-rw-r--r-- | usr/src/uts/common/io/uath/uath.c | 9 |
4 files changed, 86 insertions, 30 deletions
diff --git a/usr/src/lib/libcrypt/common/cryptio.c b/usr/src/lib/libcrypt/common/cryptio.c index 78b96aff48..613fdb3a31 100644 --- a/usr/src/lib/libcrypt/common/cryptio.c +++ b/usr/src/lib/libcrypt/common/cryptio.c @@ -25,9 +25,7 @@ */ /* Copyright (c) 1988 AT&T */ -/* All Rights Reserved */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* All Rights Reserved */ #pragma weak _run_setkey = run_setkey #pragma weak _run_crypt = run_crypt @@ -48,7 +46,7 @@ #define READER 0 #define WRITER 1 -#define KSIZE 8 +#define KSIZE 8 /* Global Variables */ static char key[KSIZE+1]; @@ -65,7 +63,7 @@ static int writekey(); void _exit(); int -run_setkey(int p[2], const char *keyparam) +run_setkey(int *p, const char *keyparam) { (void) mutex_lock(&lock); if (cryptopen(p) == -1) { @@ -119,7 +117,7 @@ writekey(int p[2], char *keyarg) int -run_crypt(long offset, char *buffer, unsigned int count, int p[2]) +run_crypt(long offset, char *buffer, unsigned int count, int *p) { struct header header; void (*pstat) (); @@ -193,7 +191,7 @@ crypt_close_nolock(int p[2]) } int -crypt_close(int p[2]) +crypt_close(int *p) { (void) mutex_lock(&lock); (void) crypt_close_nolock(p); diff --git a/usr/src/tools/cscope-fast/cgrep.c b/usr/src/tools/cscope-fast/cgrep.c index 7875789364..bd7c3e8043 100644 --- a/usr/src/tools/cscope-fast/cgrep.c +++ b/usr/src/tools/cscope-fast/cgrep.c @@ -20,16 +20,13 @@ * CDDL HEADER END */ /* Copyright (c) 1990 AT&T */ -/* All Rights Reserved */ - +/* All Rights Reserved */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * cscope - interactive C symbol or text cross-reference * @@ -209,7 +206,7 @@ typedef struct { #define ADD(N) if (qtail) qtail = qtail->next = NEW(N); \ else qtail = qhead = NEW(N) #define DEL() { Link *_l = qhead; if ((qhead = qhead->next) == NULL) \ - qtail = NULL; _l->next = froot; froot = _l; } + { qtail = NULL; } _l->next = froot; froot = _l; } static uchar_t *buffer; static uchar_t *bufend; @@ -718,10 +715,8 @@ followstate(re_re *r, State *s, int a, Positionset *fpos) for (q = e->follow, eq = q + e->flen; q < eq; q++) { SET(fpos, *q, r->posbase[j].fcount + 1) #ifdef DEBUG - printf("CHAR %c FC %c COUNT %d\n", - a, - r->ptr[*q]->lit, - r->posbase[j].fcount+1); + printf("CHAR %c FC %c COUNT %d\n", a, + r->ptr[*q]->lit, r->posbase[j].fcount+1); #endif } } @@ -889,8 +884,8 @@ stateof(re_re *r, Positionset *ps) if (s->npos == ps->count) { for (p = s->pos+r->posbase, e = p+s->npos; p < e; p++) if (ps->base[p->id].id == 0 || - ps->base[p->id].fcount != p->fcount) - goto next; + ps->base[p->id].fcount != p->fcount) + goto next; return (s); } next:; @@ -962,8 +957,9 @@ lex(re_re *r, PATTERN *pat) if (pat->loc1 == pat->loc2) { err("syntax error - missing character " "after \\"); - } else - toklit = r->cmap[*pat->loc1++]; + } else { + toklit = r->cmap[*pat->loc1++]; + } break; case '^': case '$': toktype = Literal; toklit = NL; break; default: toktype = Literal; toklit = r->cmap[toklit]; break; @@ -990,8 +986,7 @@ ccl(PATTERN *pat, uchar_t *tab) lastc = *pat->loc1++; } /* scan for chars */ - for (; (pat->loc1 < pat->loc2) && (*pat->loc1 != ']'); - pat->loc1++) { + for (; (pat->loc1 < pat->loc2) && (*pat->loc1 != ']'); pat->loc1++) { if (*pat->loc1 == '-') { if (lastc < 0) CCL_SET(tab, pat->cmap['-']); else range = 1; @@ -1109,7 +1104,7 @@ d1(re_re *r, PATTERN *pat) e = d2(r, pat); while ((toktype == Literal) || (toktype == Dot) || (toktype == Lpar) || - (toktype == Backslash) || (toktype == Charclass)) { + (toktype == Backslash) || (toktype == Charclass)) { f = d2(r, pat); e = newexpr(Cat, 0, e, f); } @@ -1784,7 +1779,7 @@ fgetfile(LINE *cur_ptr) */ int bytes; /* bytes read in current buffer */ int bufsize = MAXBUFSIZE; /* free space in data buffer */ - int save_current; + int save_current; uchar_t *begin = cur_ptr->prntbuf; /* diff --git a/usr/src/uts/common/fs/tmpfs/tmp_dir.c b/usr/src/uts/common/fs/tmpfs/tmp_dir.c index 1a620642cc..d689c512c1 100644 --- a/usr/src/uts/common/fs/tmpfs/tmp_dir.c +++ b/usr/src/uts/common/fs/tmpfs/tmp_dir.c @@ -54,6 +54,11 @@ static int tdiraddentry(struct tmpnode *, struct tmpnode *, char *, #define T_HASH_SIZE 8192 /* must be power of 2 */ #define T_MUTEX_SIZE 64 +/* Non-static so compilers won't constant-fold these away. */ +clock_t tmpfs_rename_backoff_delay = 1; +unsigned int tmpfs_rename_backoff_tries = 0; +unsigned long tmpfs_rename_loops = 0; + static struct tdirent *t_hashtable[T_HASH_SIZE]; static kmutex_t t_hashmutex[T_MUTEX_SIZE]; @@ -266,8 +271,65 @@ tdirenter( * to see if it has been removed while it was unlocked. */ if (op == DE_LINK || op == DE_RENAME) { - if (tp != dir) - rw_enter(&tp->tn_rwlock, RW_WRITER); + if (tp != dir) { + unsigned int tries = 0; + + /* + * If we are acquiring tp->tn_rwlock (for SOURCE) + * inside here, we must consider the following: + * + * - dir->tn_rwlock (TARGET) is already HELD (see + * above ASSERT()). + * + * - It is possible our SOURCE is a parent of our + * TARGET. Yes it's unusual, but it will return an + * error below via tdircheckpath(). + * + * - It is also possible that another thread, + * concurrent to this one, is performing + * rmdir(TARGET), which means it will first acquire + * SOURCE's lock, THEN acquire TARGET's lock, which + * could result in this thread holding TARGET and + * trying for SOURCE, but the other thread holding + * SOURCE and trying for TARGET. This is deadlock, + * and it's inducible. + * + * To prevent this, we borrow some techniques from UFS + * and rw_tryenter(), delaying if we fail, and + * if someone tweaks the number of backoff tries to be + * nonzero, return EBUSY after that number of tries. + */ + while (!rw_tryenter(&tp->tn_rwlock, RW_WRITER)) { + /* + * Sloppy, but this is a diagnostic so atomic + * increment would be overkill. + */ + tmpfs_rename_loops++; + + if (tmpfs_rename_backoff_tries != 0) { + if (tries > tmpfs_rename_backoff_tries) + return (EBUSY); + tries++; + } + /* + * NOTE: We're still holding dir->tn_rwlock, + * so drop it over the delay, so any other + * thread can get its business done. + * + * No state change or state inspection happens + * prior to here, so it is not wholly dangerous + * to release-and-reacquire dir->tn_rwlock. + * + * Hold the vnode of dir in case it gets + * released by another thread, though. + */ + VN_HOLD(TNTOV(dir)); + rw_exit(&dir->tn_rwlock); + delay(tmpfs_rename_backoff_delay); + rw_enter(&dir->tn_rwlock, RW_WRITER); + VN_RELE(TNTOV(dir)); + } + } mutex_enter(&tp->tn_tlock); if (tp->tn_nlink == 0) { mutex_exit(&tp->tn_tlock); diff --git a/usr/src/uts/common/io/uath/uath.c b/usr/src/uts/common/io/uath/uath.c index 4d24e55316..ee8469b0af 100644 --- a/usr/src/uts/common/io/uath/uath.c +++ b/usr/src/uts/common/io/uath/uath.c @@ -241,12 +241,13 @@ static int uath_loadsym(ddi_modhandle_t, char *, char **, size_t *); static int uath_loadfirmware(struct uath_softc *); static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd *, int, int); -static int uath_init_cmd_list(struct uath_softc *); +static int uath_init_cmd_list(struct uath_softc *); static void uath_free_cmd_list(struct uath_cmd *, int); static int uath_host_available(struct uath_softc *); static void uath_get_capability(struct uath_softc *, uint32_t, uint32_t *); static int uath_get_devcap(struct uath_softc *); -static int uath_get_devstatus(struct uath_softc *, uint8_t *); +static int uath_get_devstatus(struct uath_softc *, + uint8_t [IEEE80211_ADDR_LEN]); static int uath_get_status(struct uath_softc *, uint32_t, void *, int); static void uath_cmd_lock_init(struct uath_cmd_lock *); @@ -1534,12 +1535,12 @@ uath_tx_data_xfer(struct uath_softc *sc, mblk_t *mp) req->bulk_len = msgdsize(mp); req->bulk_data = mp; - req->bulk_client_private = (usb_opaque_t)sc; + req->bulk_client_private = (usb_opaque_t)sc; req->bulk_timeout = UATH_DATA_TIMEOUT; req->bulk_attributes = USB_ATTRS_AUTOCLEARING; req->bulk_cb = uath_data_txeof; req->bulk_exc_cb = uath_data_txeof; - req->bulk_completion_reason = 0; + req->bulk_completion_reason = 0; req->bulk_cb_flags = 0; if ((err = usb_pipe_bulk_xfer(sc->tx_data_pipe, req, 0)) != |