--- a/sys/kern/vfs_quota.c +++ b/sys/kern/vfs_quota.c @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -333,47 +334,61 @@ const char *path; struct plistref pref; prop_dictionary_t dict; + prop_dictionary_t odict; prop_object_t args; - char *cmd; + const char *cmd; prop_array_t pa_out; struct nlookupdata nd; int error; if (!vfs_quota_enabled) return EOPNOTSUPP; + error = caps_priv_check_td(curthread, SYSCAP_NOQUOTA_WR); + if (error) + return (error); path = vqa->path; error = copyin(vqa->pref, &pref, sizeof(pref)); + if (error) + return (error); error = prop_dictionary_copyin(&pref, &dict); if (error) return(error); /* we have a path, get its mount point */ error = nlookup_init(&nd, path, UIO_USERSPACE, 0); - if (error) + if (error) { + prop_object_release(dict); return (error); + } error = nlookup(&nd); - if (error) + if (error) { + prop_object_release(dict); + nlookup_done(&nd); return (error); + } nch = nd.nl_nch; cache_zero(&nd.nl_nch); nlookup_done(&nd); /* get the command */ - if (prop_dictionary_get_cstring(dict, "command", &cmd) == 0) { + if (prop_dictionary_get_cstring_nocopy(dict, "command", &cmd) == 0) { kprintf("sys_vquotactl(): couldn't get command\n"); cache_put(&nch); + prop_object_release(dict); return EINVAL; } args = prop_dictionary_get(dict, "arguments"); if (args == NULL) { kprintf("couldn't get arguments\n"); cache_put(&nch); + prop_object_release(dict); return EINVAL; } pa_out = prop_array_create(); if (pa_out == NULL) { cache_put(&nch); + prop_object_release(dict); return ENOMEM; } @@ -398,15 +413,26 @@ goto done; } cache_put(&nch); + prop_object_release(pa_out); + prop_object_release(dict); return EINVAL; done: /* kernel to userland */ - dict = prop_dictionary_create(); - error = prop_dictionary_set(dict, "returned data", pa_out); + odict = prop_dictionary_create(); + if (odict == NULL) { + cache_put(&nch); + prop_object_release(pa_out); + prop_object_release(dict); + return ENOMEM; + } + error = prop_dictionary_set(odict, "returned data", pa_out); - error = prop_dictionary_copyout(&pref, dict); + error = prop_dictionary_copyout(&pref, odict); error = copyout(&pref, vqa->pref, sizeof(pref)); + prop_object_release(odict); + prop_object_release(pa_out); + prop_object_release(dict); cache_put(&nch); return error; --- a/sys/kern/kern_udev.c +++ b/sys/kern/kern_udev.c @@ -1010,6 +1010,7 @@ error = prop_dictionary_copyout_ioctl(pref, cmd, odict); + prop_object_release(ctx.cdevs); prop_object_release(odict); return error; }