From 2919ef7927bf2497d9230fdfd7b49ce2b2effb53 Mon Sep 17 00:00:00 2001 From: bz Date: Mon, 6 Jun 2016 20:57:24 +0000 Subject: Implement a `show panic` command to DDB which will helpfully print the panic string again if set, in case it scrolled out of the active window. This avoids having to remember the symbol name. Also add a show callout command to DDB in order to inspect some struct callout fields in case of panics in the callout code. This may help to see if there was memory corruption or to further ease debugging problems. Obtained from: projects/vnet MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Reviewed by: jhb (comment only on the show panic initally) Differential Revision: https://reviews.freebsd.org/D4527 --- sys/kern/kern_shutdown.c | 11 +++++++++++ sys/kern/kern_timeout.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) (limited to 'sys/kern') diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index db93e34..78227e7 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -929,3 +929,14 @@ mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver, strlcpy(kdh->panicstring, panicstr, sizeof(kdh->panicstring)); kdh->parity = kerneldump_parity(kdh); } + +#ifdef DDB +DB_SHOW_COMMAND(panic, db_show_panic) +{ + + if (panicstr == NULL) + db_printf("panicstr not set\n"); + else + db_printf("panic: %s\n", panicstr); +} +#endif diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 50e6db9..244e5c9 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include "opt_callout_profiling.h" +#include "opt_ddb.h" #if defined(__arm__) #include "opt_timer.h" #endif @@ -60,6 +61,11 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef DDB +#include +#include +#endif + #ifdef SMP #include #endif @@ -1615,3 +1621,34 @@ SYSCTL_PROC(_kern, OID_AUTO, callout_stat, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 0, sysctl_kern_callout_stat, "I", "Dump immediate statistic snapshot of the scheduled callouts"); + +#ifdef DDB +static void +_show_callout(struct callout *c) +{ + + db_printf("callout %p\n", c); +#define C_DB_PRINTF(f, e) db_printf(" %s = " f "\n", #e, c->e); + db_printf(" &c_links = %p\n", &(c->c_links)); + C_DB_PRINTF("%" PRId64, c_time); + C_DB_PRINTF("%" PRId64, c_precision); + C_DB_PRINTF("%p", c_arg); + C_DB_PRINTF("%p", c_func); + C_DB_PRINTF("%p", c_lock); + C_DB_PRINTF("%#x", c_flags); + C_DB_PRINTF("%#x", c_iflags); + C_DB_PRINTF("%d", c_cpu); +#undef C_DB_PRINTF +} + +DB_SHOW_COMMAND(callout, db_show_callout) +{ + + if (!have_addr) { + db_printf("usage: show callout \n"); + return; + } + + _show_callout((struct callout *)addr); +} +#endif /* DDB */ -- cgit v1.1 From f66cc0d4f806c9abbd7884854e487d2951c4b8d5 Mon Sep 17 00:00:00 2001 From: mmel Date: Tue, 7 Jun 2016 05:08:24 +0000 Subject: INTRNG: As follow up of r301451, implement mapping and configuration of gpio pin interrupts by new way. Note: This removes last consumer of intr_ddata machinery and we remove it in separate commit. --- sys/kern/subr_intr.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index 5d18ea2..9161cf0 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -147,7 +147,9 @@ struct intr_dev_data { }; static struct intr_dev_data *intr_ddata_tab[2 * NIRQ]; +#if 0 static u_int intr_ddata_first_unused; +#endif #define IRQ_DDATA_BASE 10000 CTASSERT(IRQ_DDATA_BASE > nitems(irq_sources)); @@ -534,6 +536,7 @@ intr_isrc_init_on_cpu(struct intr_irqsrc *isrc, u_int cpu) } #endif +#if 0 static struct intr_dev_data * intr_ddata_alloc(u_int extsize) { @@ -556,6 +559,7 @@ intr_ddata_alloc(u_int extsize) ddata->idd_data = (struct intr_map_data *)((uintptr_t)ddata + size); return (ddata); } +#endif static struct intr_irqsrc * intr_ddata_lookup(u_int irq, struct intr_map_data **datap) @@ -620,30 +624,6 @@ intr_acpi_map_irq(device_t dev, u_int irq, enum intr_polarity pol, } #endif -/* - * Store GPIO interrupt decription in framework and return unique interrupt - * number (resource handle) associated with it. - */ -u_int -intr_gpio_map_irq(device_t dev, u_int pin_num, u_int pin_flags, u_int intr_mode) -{ - struct intr_dev_data *ddata; - struct intr_map_data_gpio *dag; - - ddata = intr_ddata_alloc(sizeof(struct intr_map_data_gpio)); - if (ddata == NULL) - return (INTR_IRQ_INVALID); /* no space left */ - - ddata->idd_dev = dev; - ddata->idd_data->type = INTR_MAP_DATA_GPIO; - - dag = (struct intr_map_data_gpio *)ddata->idd_data; - dag->gpio_pin_num = pin_num; - dag->gpio_pin_flags = pin_flags; - dag->gpio_intr_mode = intr_mode; - return (ddata->idd_irq); -} - #ifdef INTR_SOLO /* * Setup filter into interrupt source. -- cgit v1.1 From 707fd866b9274c3ac23bdcbe6da41f78cf5cba84 Mon Sep 17 00:00:00 2001 From: skra Date: Tue, 7 Jun 2016 09:03:27 +0000 Subject: Remove temporary solution for storing interrupt mapping data as it's not needed after r301451 and follow-ups r301453, r301539. This makes INTRNG clean of all additions related to various buses. --- sys/kern/subr_intr.c | 154 ++++----------------------------------------------- 1 file changed, 11 insertions(+), 143 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c index 9161cf0..64d37ed 100644 --- a/sys/kern/subr_intr.c +++ b/sys/kern/subr_intr.c @@ -35,10 +35,8 @@ __FBSDID("$FreeBSD$"); * - to complete things for removable PICs */ -#include "opt_acpi.h" #include "opt_ddb.h" #include "opt_hwpmc_hooks.h" -#include "opt_platform.h" #include #include @@ -123,37 +121,6 @@ static struct mtx isrc_table_lock; static struct intr_irqsrc *irq_sources[NIRQ]; u_int irq_next_free; -/* - * XXX - All stuff around struct intr_dev_data is considered as temporary - * until better place for storing struct intr_map_data will be find. - * - * For now, there are two global interrupt numbers spaces: - * <0, NIRQ) ... interrupts without config data - * managed in irq_sources[] - * IRQ_DDATA_BASE + <0, 2 * NIRQ) ... interrupts with config data - * managed in intr_ddata_tab[] - * - * Read intr_ddata_lookup() to see how these spaces are worked with. - * Note that each interrupt number from second space duplicates some number - * from first space at this moment. An interrupt number from first space can - * be duplicated even multiple times in second space. - */ -struct intr_dev_data { - device_t idd_dev; - intptr_t idd_xref; - u_int idd_irq; - struct intr_map_data * idd_data; - struct intr_irqsrc * idd_isrc; -}; - -static struct intr_dev_data *intr_ddata_tab[2 * NIRQ]; -#if 0 -static u_int intr_ddata_first_unused; -#endif - -#define IRQ_DDATA_BASE 10000 -CTASSERT(IRQ_DDATA_BASE > nitems(irq_sources)); - #ifdef SMP static boolean_t irq_assign_cpu = FALSE; #endif @@ -536,94 +503,6 @@ intr_isrc_init_on_cpu(struct intr_irqsrc *isrc, u_int cpu) } #endif -#if 0 -static struct intr_dev_data * -intr_ddata_alloc(u_int extsize) -{ - struct intr_dev_data *ddata; - size_t size; - - size = sizeof(*ddata); - ddata = malloc(size + extsize, M_INTRNG, M_WAITOK | M_ZERO); - - mtx_lock(&isrc_table_lock); - if (intr_ddata_first_unused >= nitems(intr_ddata_tab)) { - mtx_unlock(&isrc_table_lock); - free(ddata, M_INTRNG); - return (NULL); - } - intr_ddata_tab[intr_ddata_first_unused] = ddata; - ddata->idd_irq = IRQ_DDATA_BASE + intr_ddata_first_unused++; - mtx_unlock(&isrc_table_lock); - - ddata->idd_data = (struct intr_map_data *)((uintptr_t)ddata + size); - return (ddata); -} -#endif - -static struct intr_irqsrc * -intr_ddata_lookup(u_int irq, struct intr_map_data **datap) -{ - int error; - struct intr_irqsrc *isrc; - struct intr_dev_data *ddata; - - isrc = isrc_lookup(irq); - if (isrc != NULL) { - if (datap != NULL) - *datap = NULL; - return (isrc); - } - - if (irq < IRQ_DDATA_BASE) - return (NULL); - - irq -= IRQ_DDATA_BASE; - if (irq >= nitems(intr_ddata_tab)) - return (NULL); - - ddata = intr_ddata_tab[irq]; - if (ddata->idd_isrc == NULL) { - error = intr_map_irq(ddata->idd_dev, ddata->idd_xref, - ddata->idd_data, &irq); - if (error != 0) - return (NULL); - ddata->idd_isrc = isrc_lookup(irq); - } - if (datap != NULL) - *datap = ddata->idd_data; - return (ddata->idd_isrc); -} - -#ifdef DEV_ACPI -/* - * Map interrupt source according to ACPI info into framework. If such mapping - * does not exist, create it. Return unique interrupt number (resource handle) - * associated with mapped interrupt source. - */ -u_int -intr_acpi_map_irq(device_t dev, u_int irq, enum intr_polarity pol, - enum intr_trigger trig) -{ - struct intr_map_data_acpi *daa; - struct intr_dev_data *ddata; - - ddata = intr_ddata_alloc(sizeof(struct intr_map_data_acpi)); - if (ddata == NULL) - return (INTR_IRQ_INVALID); /* no space left */ - - ddata->idd_dev = dev; - ddata->idd_data->type = INTR_MAP_DATA_ACPI; - - daa = (struct intr_map_data_acpi *)ddata->idd_data; - daa->irq = irq; - daa->pol = pol; - daa->trig = trig; - - return (ddata->idd_irq); -} -#endif - #ifdef INTR_SOLO /* * Setup filter into interrupt source. @@ -1054,14 +933,11 @@ intr_alloc_irq(device_t dev, struct resource *res) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - data = rman_get_virtual(res); - if (data == NULL) - isrc = intr_ddata_lookup(rman_get_start(res), &data); - else - isrc = isrc_lookup(rman_get_start(res)); + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL) return (EINVAL); + data = rman_get_virtual(res); return (PIC_ALLOC_INTR(isrc->isrc_dev, isrc, res, data)); } @@ -1074,14 +950,11 @@ intr_release_irq(device_t dev, struct resource *res) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - data = rman_get_virtual(res); - if (data == NULL) - isrc = intr_ddata_lookup(rman_get_start(res), &data); - else - isrc = isrc_lookup(rman_get_start(res)); + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL) return (EINVAL); + data = rman_get_virtual(res); return (PIC_RELEASE_INTR(isrc->isrc_dev, isrc, res, data)); } @@ -1097,14 +970,11 @@ intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt, KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - data = rman_get_virtual(res); - if (data == NULL) - isrc = intr_ddata_lookup(rman_get_start(res), &data); - else - isrc = isrc_lookup(rman_get_start(res)); + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL) return (EINVAL); + data = rman_get_virtual(res); name = device_get_nameunit(dev); #ifdef INTR_SOLO @@ -1161,14 +1031,12 @@ intr_teardown_irq(device_t dev, struct resource *res, void *cookie) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - data = rman_get_virtual(res); - if (data == NULL) - isrc = intr_ddata_lookup(rman_get_start(res), &data); - else - isrc = isrc_lookup(rman_get_start(res)); + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL || isrc->isrc_handlers == 0) return (EINVAL); + data = rman_get_virtual(res); + #ifdef INTR_SOLO if (isrc->isrc_filter != NULL) { if (isrc != cookie) @@ -1211,7 +1079,7 @@ intr_describe_irq(device_t dev, struct resource *res, void *cookie, KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), NULL); + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL || isrc->isrc_handlers == 0) return (EINVAL); #ifdef INTR_SOLO @@ -1243,7 +1111,7 @@ intr_bind_irq(device_t dev, struct resource *res, int cpu) KASSERT(rman_get_start(res) == rman_get_end(res), ("%s: more interrupts in resource", __func__)); - isrc = intr_ddata_lookup(rman_get_start(res), NULL); + isrc = isrc_lookup(rman_get_start(res)); if (isrc == NULL || isrc->isrc_handlers == 0) return (EINVAL); #ifdef INTR_SOLO -- cgit v1.1 From 17ff1e5b262125b4d633e4d2f266a27e83cadb49 Mon Sep 17 00:00:00 2001 From: oshogbo Date: Wed, 8 Jun 2016 02:09:14 +0000 Subject: Introduce the PD_CLOEXEC for pdfork(2). Reviewed by: mjg --- sys/kern/kern_fork.c | 8 ++++++-- sys/kern/sys_procdesc.c | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index e004097..1260c98 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -827,6 +827,10 @@ fork1(struct thread *td, struct fork_req *fr) /* Must provide a place to put a procdesc if creating one. */ if (fr->fr_pd_fd == NULL) return (EINVAL); + + /* Check if we are using supported flags. */ + if ((fr->fr_pd_flags & ~PD_ALLOWED_AT_FORK) != 0) + return (EINVAL); } p1 = td->td_proc; @@ -878,8 +882,8 @@ fork1(struct thread *td, struct fork_req *fr) * later. */ if (flags & RFPROCDESC) { - error = falloc_caps(td, &fp_procdesc, fr->fr_pd_fd, 0, - fr->fr_pd_fcaps); + error = procdesc_falloc(td, &fp_procdesc, fr->fr_pd_fd, + fr->fr_pd_flags, fr->fr_pd_fcaps); if (error != 0) goto fail2; } diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c index 0d3b1f4..37139c1 100644 --- a/sys/kern/sys_procdesc.c +++ b/sys/kern/sys_procdesc.c @@ -243,6 +243,22 @@ procdesc_new(struct proc *p, int flags) } /* + * Create a new process decriptor for the process that refers to it. + */ +int +procdesc_falloc(struct thread *td, struct file **resultfp, int *resultfd, + int flags, struct filecaps *fcaps) +{ + int fflags; + + fflags = 0; + if (flags & PD_CLOEXEC) + fflags = O_CLOEXEC; + + return (falloc_caps(td, resultfp, resultfd, fflags, fcaps)); +} + +/* * Initialize a file with a process descriptor. */ void -- cgit v1.1 From ef4ada7b7665029bd2c1c35e80c1a18df361b214 Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 8 Jun 2016 04:37:03 +0000 Subject: Old process credentials for setuid execve must not be dereferenced when the process credentials were not changed. This can happen if an error occured trying to activate the setuid binary. And on error, if new credentials were not yet assigned, they must be freed to not create the leak. Use oldcred == NULL as the predicate to detect credential reassignment. Reported and tested by: pho Sponsored by: The FreeBSD Foundation --- sys/kern/kern_exec.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index d2de3c8..63d855d 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -806,8 +806,11 @@ interpret: /* * Set the new credentials. */ - if (imgp->newcred != NULL) + if (imgp->newcred != NULL) { proc_set_cred(p, imgp->newcred); + crfree(oldcred); + oldcred = NULL; + } /* * Store the vp for use in procfs. This vnode was referenced by namei @@ -918,8 +921,9 @@ exec_fail: SDT_PROBE1(proc, , , exec__failure, error); } - if (imgp->newcred != NULL) - crfree(oldcred); + if (imgp->newcred != NULL && oldcred != NULL) + crfree(imgp->newcred); + #ifdef MAC mac_execve_exit(imgp); mac_execve_interpreter_exit(interpvplabel); -- cgit v1.1 From cdf94f56b034317679d0a625d023f2d1f11ee5c6 Mon Sep 17 00:00:00 2001 From: markj Date: Thu, 9 Jun 2016 13:17:08 +0000 Subject: Fix some cosmetic issues in kern_fail.c omitted from r296927. Obtained from: Matthew Bryan --- sys/kern/kern_fail.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_fail.c b/sys/kern/kern_fail.c index ec466dd..b5bf066 100644 --- a/sys/kern/kern_fail.c +++ b/sys/kern/kern_fail.c @@ -82,13 +82,13 @@ static MALLOC_DEFINE(M_FAIL_POINT, "Fail Points", "fail points system"); #define fp_malloc(size, flags) malloc((size), M_FAIL_POINT, (flags)) #define fs_free(ptr) fp_free(ptr) #define fs_malloc() fp_malloc(sizeof(struct fail_point_setting), \ - M_WAITOK | M_ZERO) + M_WAITOK | M_ZERO) - /** - * These define the wchans that are used for sleeping, pausing respectively. - * They are chosen arbitrarily but need to be distinct to the failpoint and - * the sleep/pause distinction. - */ +/** + * These define the wchans that are used for sleeping, pausing respectively. + * They are chosen arbitrarily but need to be distinct to the failpoint and + * the sleep/pause distinction. + */ #define FP_SLEEP_CHANNEL(fp) (void*)(fp) #define FP_PAUSE_CHANNEL(fp) __DEVOLATILE(void*, &fp->fp_setting) @@ -166,7 +166,7 @@ struct fail_point_entry { enum fail_point_t fe_type; /**< type of entry */ int fe_arg; /**< argument to type (e.g. return value) */ int fe_prob; /**< likelihood of firing in millionths */ - int fe_count; /**< number of times to fire, -1 means infinite */ + int32_t fe_count; /**< number of times to fire, -1 means infinite */ pid_t fe_pid; /**< only fail for this process */ struct fail_point *fe_parent; /**< backpointer to fp */ TAILQ_ENTRY(fail_point_entry) fe_entries; /**< next entry ptr */ @@ -354,7 +354,7 @@ fail_point_eval_swap_out(struct fail_point *fp, /* Free up any zero-ref entries in the garbage queue */ static void -fail_point_garbage_collect() +fail_point_garbage_collect(void) { struct fail_point_setting *fs_current, *fs_next; struct fail_point_setting_garbage fp_ents_free_list; @@ -441,7 +441,7 @@ fail_point_sleep(struct fail_point *fp, int msecs, fp->fp_pre_sleep_fn(fp->fp_pre_sleep_arg); timeout(fp->fp_post_sleep_fn, fp->fp_post_sleep_arg, - timo); + timo); *pret = FAIL_POINT_RC_QUEUED; } } @@ -635,7 +635,6 @@ abort: fail_point_setting_release_ref(fp); return (ret); - } /** @@ -844,19 +843,17 @@ end: /** * Handle kernel failpoint set/get. */ - int fail_point_sysctl(SYSCTL_HANDLER_ARGS) { struct fail_point *fp; char *buf; - struct sbuf *sb_check; - struct sbuf sb; + struct sbuf sb, *sb_check; int error; + buf = NULL; error = 0; fp = arg1; - buf = NULL; sb_check = sbuf_new(&sb, NULL, 1024, SBUF_AUTOEXTEND); if (sb_check != &sb) @@ -949,7 +946,6 @@ fail_sysctl_drain_func(void *sysctl_args, const char *buf, int len) return (len); } - /** * Internal helper function to translate a human-readable failpoint string * into a internally-parsable fail_point structure. -- cgit v1.1 From 88eec3fa5bec1d298f9e526ff7531559c89837a1 Mon Sep 17 00:00:00 2001 From: jamie Date: Thu, 9 Jun 2016 15:34:33 +0000 Subject: Remove a comment that was part of copied code, and is misleading in the new location. --- sys/kern/sysv_msg.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c index 2a855a6..ba3995c 100644 --- a/sys/kern/sysv_msg.c +++ b/sys/kern/sysv_msg.c @@ -320,12 +320,6 @@ msgunload() #endif for (msqid = 0; msqid < msginfo.msgmni; msqid++) { - /* - * Look for an unallocated and unlocked msqid_ds. - * msqid_ds's can be locked by msgsnd or msgrcv while - * they are copying the message in/out. We can't - * re-use the entry until they release it. - */ msqkptr = &msqids[msqid]; if (msqkptr->u.msg_qbytes != 0 || (msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0) -- cgit v1.1 From debe558799a039749c66e1bfa41c6d004cd4f0f6 Mon Sep 17 00:00:00 2001 From: jamie Date: Thu, 9 Jun 2016 16:41:41 +0000 Subject: Make sure the OSD methods for jail set and remove can't run concurrently, by holding allprison_lock exclusively (even if only for a moment before downgrading) on all paths that call PR_METHOD_REMOVE. Since they may run on a downgraded lock, it's still possible for them to run concurrently with PR_METHOD_GET, which will need to use the prison lock. --- sys/kern/kern_jail.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 35e270a..ea4b628 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -2383,7 +2383,14 @@ sys_jail_attach(struct thread *td, struct jail_attach_args *uap) if (error) return (error); - sx_slock(&allprison_lock); + /* + * Start with exclusive hold on allprison_lock to ensure that a possible + * PR_METHOD_REMOVE call isn't concurrent with jail_set or jail_remove. + * But then immediately downgrade it since we don't need to stop + * readers. + */ + sx_xlock(&allprison_lock); + sx_downgrade(&allprison_lock); pr = prison_find_child(td->td_ucred->cr_prison, uap->jid); if (pr == NULL) { sx_sunlock(&allprison_lock); @@ -2601,9 +2608,11 @@ prison_complete(void *context, int pending) { struct prison *pr = context; + sx_xlock(&allprison_lock); mtx_lock(&pr->pr_mtx); prison_deref(pr, pr->pr_uref - ? PD_DEREF | PD_DEUREF | PD_LOCKED : PD_LOCKED); + ? PD_DEREF | PD_DEUREF | PD_LOCKED | PD_LIST_XLOCKED + : PD_LOCKED | PD_LIST_XLOCKED); } /* @@ -2647,13 +2656,8 @@ prison_deref(struct prison *pr, int flags) */ if (lasturef) { if (!(flags & (PD_LIST_SLOCKED | PD_LIST_XLOCKED))) { - if (ref > 1) { - sx_slock(&allprison_lock); - flags |= PD_LIST_SLOCKED; - } else { - sx_xlock(&allprison_lock); - flags |= PD_LIST_XLOCKED; - } + sx_xlock(&allprison_lock); + flags |= PD_LIST_XLOCKED; } (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL); mtx_lock(&pr->pr_mtx); -- cgit v1.1 From 5ebc37ce13cc781ebe2b412f696455def98d857b Mon Sep 17 00:00:00 2001 From: cem Date: Thu, 9 Jun 2016 18:24:51 +0000 Subject: kvprintf: Pad %*c to width, like %*s Sponsored by: EMC / Isilon Storage Division --- sys/kern/subr_prf.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'sys/kern') diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c index ce781d9..5bcf39b 100644 --- a/sys/kern/subr_prf.c +++ b/sys/kern/subr_prf.c @@ -730,7 +730,15 @@ reswitch: switch (ch = (u_char)*fmt++) { PCHAR('>'); break; case 'c': + width -= 1; + + if (!ladjust && width > 0) + while (width--) + PCHAR(padc); PCHAR(va_arg(ap, int)); + if (ladjust && width > 0) + while (width--) + PCHAR(padc); break; case 'D': up = va_arg(ap, u_char *); -- cgit v1.1 From a9972a75afee0d3efc7bddffe276af8c792912a1 Mon Sep 17 00:00:00 2001 From: cem Date: Thu, 9 Jun 2016 18:27:41 +0000 Subject: Add DDB command "kldstat" It prints much the same information as kldstat(8) without any arguments. Suggested by: jhibbits Sponsored by: EMC / Isilon Storage Division --- sys/kern/kern_linker.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'sys/kern') diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index 16c39f0..4758cdc 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -54,6 +54,10 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef DDB +#include +#endif + #include #include @@ -1256,6 +1260,23 @@ kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat) return (0); } +#ifdef DDB +DB_COMMAND(kldstat, db_kldstat) +{ + linker_file_t lf; + +#define POINTER_WIDTH ((int)(sizeof(void *) * 2 + 2)) + db_printf("Id Refs Address%*c Size Name\n", POINTER_WIDTH - 7, ' '); +#undef POINTER_WIDTH + TAILQ_FOREACH(lf, &linker_files, link) { + if (db_pager_quit) + return; + db_printf("%2d %4d %p %-8zx %s\n", lf->id, lf->refs, + lf->address, lf->size, lf->filename); + } +} +#endif /* DDB */ + int sys_kldfirstmod(struct thread *td, struct kldfirstmod_args *uap) { -- cgit v1.1 From 57dc7171d01c809423dc85a3479546200b3b3cc8 Mon Sep 17 00:00:00 2001 From: oshogbo Date: Thu, 9 Jun 2016 20:23:30 +0000 Subject: Define tunable instead of using CTLFLAG_RWTUN flag with kern.corefile. The allproc_lock lock used in the sysctl_kern_corefile function is initialized in the procinit function which is called after setting sysctl values at boot. That means if we set kern.corefile at boot we will be trying to use lock with is uninitialized and machine will crash. If we define kern.corefile as tunable instead of using CTFLAG_RWTUN we will not call the sysctl_kern_corefile function and we will not use an uninitialized lock. When machine will boot then we will start using function depending on the lock. Reviewed by: pjd --- sys/kern/kern_sig.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 75a1259..f8bb87e 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -3123,6 +3123,7 @@ static int compress_user_cores = 0; #define corefilename_lock allproc_lock static char corefilename[MAXPATHLEN] = {"%N.core"}; +TUNABLE_STR("kern.corefile", corefilename, sizeof(corefilename)); static int sysctl_kern_corefile(SYSCTL_HANDLER_ARGS) @@ -3136,7 +3137,7 @@ sysctl_kern_corefile(SYSCTL_HANDLER_ARGS) return (error); } -SYSCTL_PROC(_kern, OID_AUTO, corefile, CTLTYPE_STRING | CTLFLAG_RWTUN | +SYSCTL_PROC(_kern, OID_AUTO, corefile, CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 0, sysctl_kern_corefile, "A", "Process corefile name format string"); -- cgit v1.1 From 91dc125e2d62a46ec88abc017cb7d8f07c9c166e Mon Sep 17 00:00:00 2001 From: jamie Date: Thu, 9 Jun 2016 20:39:57 +0000 Subject: Clean up some logic in jail error messages, replacing a missing test and a redundant test with a single correct test. --- sys/kern/kern_jail.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index ea4b628..7bc496e 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -1929,19 +1929,17 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) vrele(root); done_errmsg: if (error) { - vfs_getopt(opts, "errmsg", (void **)&errmsg, &errmsg_len); - if (errmsg_len > 0) { + if (vfs_getopt(opts, "errmsg", (void **)&errmsg, + &errmsg_len) == 0 && errmsg_len > 0) { errmsg_pos = 2 * vfs_getopt_pos(opts, "errmsg") + 1; - if (errmsg_pos > 0) { - if (optuio->uio_segflg == UIO_SYSSPACE) - bcopy(errmsg, - optuio->uio_iov[errmsg_pos].iov_base, - errmsg_len); - else - copyout(errmsg, - optuio->uio_iov[errmsg_pos].iov_base, - errmsg_len); - } + if (optuio->uio_segflg == UIO_SYSSPACE) + bcopy(errmsg, + optuio->uio_iov[errmsg_pos].iov_base, + errmsg_len); + else + copyout(errmsg, + optuio->uio_iov[errmsg_pos].iov_base, + errmsg_len); } } done_free: -- cgit v1.1 From 786e18e2983525384b47757362dc5a8c151f650a Mon Sep 17 00:00:00 2001 From: jamie Date: Thu, 9 Jun 2016 20:43:14 +0000 Subject: Re-order some jail parameter reading to prevent a vnode leak. --- sys/kern/kern_jail.c | 80 ++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 40 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 7bc496e..74522d9 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -920,6 +920,46 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) } #endif + error = vfs_getopt(opts, "osrelease", (void **)&osrelstr, &len); + if (error == ENOENT) + osrelstr = NULL; + else if (error != 0) + goto done_free; + else { + if (flags & JAIL_UPDATE) { + error = EINVAL; + vfs_opterror(opts, + "osrelease cannot be changed after creation"); + goto done_errmsg; + } + if (len == 0 || len >= OSRELEASELEN) { + error = EINVAL; + vfs_opterror(opts, + "osrelease string must be 1-%d bytes long", + OSRELEASELEN - 1); + goto done_errmsg; + } + } + + error = vfs_copyopt(opts, "osreldate", &osreldt, sizeof(osreldt)); + if (error == ENOENT) + osreldt = 0; + else if (error != 0) + goto done_free; + else { + if (flags & JAIL_UPDATE) { + error = EINVAL; + vfs_opterror(opts, + "osreldate cannot be changed after creation"); + goto done_errmsg; + } + if (osreldt == 0) { + error = EINVAL; + vfs_opterror(opts, "osreldate cannot be 0"); + goto done_errmsg; + } + } + fullpath_disabled = 0; root = NULL; error = vfs_getopt(opts, "path", (void **)&path, &len); @@ -975,46 +1015,6 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) } } - error = vfs_getopt(opts, "osrelease", (void **)&osrelstr, &len); - if (error == ENOENT) - osrelstr = NULL; - else if (error != 0) - goto done_free; - else { - if (flags & JAIL_UPDATE) { - error = EINVAL; - vfs_opterror(opts, - "osrelease cannot be changed after creation"); - goto done_errmsg; - } - if (len == 0 || len >= OSRELEASELEN) { - error = EINVAL; - vfs_opterror(opts, - "osrelease string must be 1-%d bytes long", - OSRELEASELEN - 1); - goto done_errmsg; - } - } - - error = vfs_copyopt(opts, "osreldate", &osreldt, sizeof(osreldt)); - if (error == ENOENT) - osreldt = 0; - else if (error != 0) - goto done_free; - else { - if (flags & JAIL_UPDATE) { - error = EINVAL; - vfs_opterror(opts, - "osreldate cannot be changed after creation"); - goto done_errmsg; - } - if (osreldt == 0) { - error = EINVAL; - vfs_opterror(opts, "osreldate cannot be 0"); - goto done_errmsg; - } - } - /* * Find the specified jail, or at least its parent. * This abuses the file error codes ENOENT and EEXIST. -- cgit v1.1 From aad828cb49a839665c04e3b71d736991a15d378f Mon Sep 17 00:00:00 2001 From: jamie Date: Thu, 9 Jun 2016 21:59:11 +0000 Subject: Fix a vnode leak when giving a child jail a too-long path when debug.disablefullpath=1. --- sys/kern/kern_jail.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sys/kern') diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 74522d9..ebd714f 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -1010,6 +1010,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags) if (len + (path[0] == '/' && strcmp(mypr->pr_path, "/") ? strlen(mypr->pr_path) : 0) > MAXPATHLEN) { error = ENAMETOOLONG; + vrele(root); goto done_free; } } -- cgit v1.1