#include <sys/vnode_internal.h>
#include <sys/mount_internal.h>
#include <sys/errno.h>
-#include <sys/malloc.h>
+#include <kern/kalloc.h>
#include <sys/filedesc.h>
#include <sys/proc_internal.h>
#include <sys/kdebug.h>
#include <sys/unistd.h> /* For _PC_NAME_MAX */
#include <sys/uio_internal.h>
#include <sys/kauth.h>
-#include <kern/kalloc.h>
+#include <kern/zalloc.h>
#include <security/audit/audit.h>
-#include <sys/dtrace.h> /* to get the prototype for strstr() in sys/dtrace_glue.h */
#if CONFIG_MACF
#include <security/mac_framework.h>
#endif
+#include <os/atomic_private.h>
#include <sys/paths.h>
#endif
static int lookup_traverse_mountpoints(struct nameidata *ndp, struct componentname *cnp, vnode_t dp, int vbusyflags, vfs_context_t ctx);
-static int lookup_handle_symlink(struct nameidata *ndp, vnode_t *new_dp, vfs_context_t ctx);
+static int lookup_handle_symlink(struct nameidata *ndp, vnode_t *new_dp, bool* dp_has_iocount, vfs_context_t ctx);
static int lookup_authorize_search(vnode_t dp, struct componentname *cnp, int dp_authorized_in_cache, vfs_context_t ctx);
static void lookup_consider_update_cache(vnode_t dvp, vnode_t vp, struct componentname *cnp, int nc_generation);
static int lookup_handle_found_vnode(struct nameidata *ndp, struct componentname *cnp, int rdonly,
static int lookup_handle_rsrc_fork(vnode_t dp, struct nameidata *ndp, struct componentname *cnp, int wantparent, vfs_context_t ctx);
#endif
-
+extern lck_rw_t * rootvnode_rw_lock;
/*
* Convert a pathname into a pointer to a locked inode.
struct vnode *dp; /* the directory we are searching */
struct vnode *usedvp = ndp->ni_dvp; /* store pointer to vp in case we must loop due to
* heavy vnode pressure */
- u_long cnpflags = ndp->ni_cnd.cn_flags; /* store in case we have to restore after loop */
+ uint32_t cnpflags = ndp->ni_cnd.cn_flags; /* store in case we have to restore after loop */
int error;
struct componentname *cnp = &ndp->ni_cnd;
vfs_context_t ctx = cnp->cn_context;
int volfs_restarts = 0;
#endif
size_t bytes_copied = 0;
- bool take_proc_lock = !(ndp->ni_flag & NAMEI_NOPROCLOCK);
- bool proc_lock_taken = false;
+ vnode_t rootdir_with_usecount = NULLVP;
+ vnode_t startdir_with_usecount = NULLVP;
+ vnode_t usedvp_dp = NULLVP;
+ int32_t old_count = 0;
+ bool dp_has_iocount = false;
fdp = p->p_fd;
cnp->cn_pnlen, &bytes_copied);
}
if (error == ENAMETOOLONG && !(cnp->cn_flags & HASBUF)) {
- MALLOC_ZONE(cnp->cn_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
- if (cnp->cn_pnbuf == NULL) {
- error = ENOMEM;
- goto error_out;
- }
-
+ cnp->cn_pnbuf = zalloc(ZV_NAMEI);
cnp->cn_flags |= HASBUF;
cnp->cn_pnlen = MAXPATHLEN;
bytes_copied = 0;
if (error) {
goto error_out;
}
- ndp->ni_pathlen = bytes_copied;
+ assert(bytes_copied <= MAXPATHLEN);
+ ndp->ni_pathlen = (u_int)bytes_copied;
bytes_copied = 0;
/*
char * realpath;
int realpath_err;
/* Attempt to resolve a legacy volfs style pathname. */
- MALLOC_ZONE(realpath, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
- if (realpath) {
- /*
- * We only error out on the ENAMETOOLONG cases where we know that
- * vfs_getrealpath translation succeeded but the path could not fit into
- * MAXPATHLEN characters. In other failure cases, we may be dealing with a path
- * that legitimately looks like /.vol/1234/567 and is not meant to be translated
- */
- if ((realpath_err = vfs_getrealpath(&cnp->cn_pnbuf[6], realpath, MAXPATHLEN, ctx))) {
- FREE_ZONE(realpath, MAXPATHLEN, M_NAMEI);
- if (realpath_err == ENOSPC || realpath_err == ENAMETOOLONG) {
- error = ENAMETOOLONG;
- goto error_out;
- }
- } else {
- if (cnp->cn_flags & HASBUF) {
- FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
- }
- cnp->cn_pnbuf = realpath;
- cnp->cn_pnlen = MAXPATHLEN;
- ndp->ni_pathlen = strlen(realpath) + 1;
- cnp->cn_flags |= HASBUF | CN_VOLFSPATH;
+ realpath = zalloc(ZV_NAMEI);
+ /*
+ * We only error out on the ENAMETOOLONG cases where we know that
+ * vfs_getrealpath translation succeeded but the path could not fit into
+ * MAXPATHLEN characters. In other failure cases, we may be dealing with a path
+ * that legitimately looks like /.vol/1234/567 and is not meant to be translated
+ */
+ if ((realpath_err = vfs_getrealpath(&cnp->cn_pnbuf[6], realpath, MAXPATHLEN, ctx))) {
+ zfree(ZV_NAMEI, realpath);
+ if (realpath_err == ENOSPC || realpath_err == ENAMETOOLONG) {
+ error = ENAMETOOLONG;
+ goto error_out;
}
+ } else {
+ size_t tmp_len;
+ if (cnp->cn_flags & HASBUF) {
+ zfree(ZV_NAMEI, cnp->cn_pnbuf);
+ }
+ cnp->cn_pnbuf = realpath;
+ cnp->cn_pnlen = MAXPATHLEN;
+ tmp_len = strlen(realpath) + 1;
+ assert(tmp_len <= UINT_MAX);
+ ndp->ni_pathlen = (u_int)tmp_len;
+ cnp->cn_flags |= HASBUF | CN_VOLFSPATH;
}
}
#endif /* CONFIG_VOLFS */
error = ENOENT;
goto error_out;
}
- ndp->ni_loopcnt = 0;
+ if (ndp->ni_flag & NAMEI_NOFOLLOW_ANY) {
+ ndp->ni_loopcnt = MAXSYMLINKS;
+ } else {
+ ndp->ni_loopcnt = 0;
+ }
/*
* determine the starting point for the translation.
- *
- * We hold the proc_dirs lock across the lookup so that the
- * process rootdir and cwd are stable (i.e. the usecounts
- * on them are mainatained for the duration of the lookup)
*/
- if (take_proc_lock) {
- assert(proc_lock_taken == false);
- proc_dirs_lock_shared(p);
- proc_lock_taken = true;
- }
+ proc_dirs_lock_shared(p);
+ lck_rw_lock_shared(rootvnode_rw_lock);
+
if (!(fdp->fd_flags & FD_CHROOT)) {
ndp->ni_rootdir = rootvnode;
} else {
/* This should be a panic */
printf("fdp->fd_rdir is not set\n");
}
+ lck_rw_unlock_shared(rootvnode_rw_lock);
+ proc_dirs_unlock_shared(p);
error = ENOENT;
goto error_out;
}
} else if (cnp->cn_flags & USEDVP) {
dp = ndp->ni_dvp;
ndp->ni_usedvp = dp;
+ usedvp_dp = dp;
} else {
dp = vfs_context_cwd(ctx);
}
if (dp == NULLVP || (dp->v_lflag & VL_DEAD)) {
dp = NULLVP;
+ lck_rw_unlock_shared(rootvnode_rw_lock);
+ proc_dirs_unlock_shared(p);
error = ENOENT;
goto error_out;
}
+ /*
+ * We need our own usecount on the root vnode and the starting dir across
+ * the lookup. There's two things that be done here. We can hold the locks
+ * (which protect the existing usecounts on the directories) across the
+ * lookup or take our own usecount. Holding the locks across the lookup can
+ * cause deadlock issues if we re-enter namei on the same thread so the
+ * correct thing to do is to acquire our own usecount.
+ *
+ * Ideally, the usecount should be obtained by vnode_get->vnode_ref->vnode_put.
+ * However when this vnode is the rootvnode, that sequence will produce a
+ * lot of vnode mutex locks and unlocks on a single vnode (the rootvnode)
+ * and will be highly contended and degrade performance. Since we have
+ * an existing usecount protected by the locks we hold, we'll just use
+ * an atomic op to increment the usecount on a vnode which already has one
+ * and can't be released becasue we have the locks which protect against that
+ * happening.
+ */
+ rootdir_with_usecount = ndp->ni_rootdir;
+ old_count = os_atomic_inc_orig(&rootdir_with_usecount->v_usecount, relaxed);
+ if (old_count < 1) {
+ panic("(1) invalid pre-increment usecount (%d) for rootdir vnode %p",
+ old_count, rootdir_with_usecount);
+ } else if (old_count == INT32_MAX) {
+ panic("(1) usecount overflow for vnode %p", rootdir_with_usecount);
+ }
+
+ if ((dp != rootdir_with_usecount) && (dp != usedvp_dp)) {
+ old_count = os_atomic_inc_orig(&dp->v_usecount, relaxed);
+ if (old_count < 1) {
+ panic("(2) invalid pre-increment usecount (%d) for vnode %p", old_count, dp);
+ } else if (old_count == INT32_MAX) {
+ panic("(2) usecount overflow for vnode %p", dp);
+ }
+ startdir_with_usecount = dp;
+ }
+
+ /* Now that we have our usecount, release the locks */
+ lck_rw_unlock_shared(rootvnode_rw_lock);
+ proc_dirs_unlock_shared(p);
+
ndp->ni_dvp = NULLVP;
ndp->ni_vp = NULLVP;
* Check for symbolic link
*/
if ((cnp->cn_flags & ISSYMLINK) == 0) {
- if (proc_lock_taken) {
- proc_dirs_unlock_shared(p);
- proc_lock_taken = false;
+ if (startdir_with_usecount) {
+ vnode_rele(startdir_with_usecount);
+ startdir_with_usecount = NULLVP;
+ }
+ if (rootdir_with_usecount) {
+ lck_rw_lock_shared(rootvnode_rw_lock);
+ if (rootdir_with_usecount == rootvnode) {
+ old_count = os_atomic_dec_orig(&rootdir_with_usecount->v_usecount, relaxed);
+ if (old_count < 2) {
+ /*
+ * There needs to have been at least 1 usecount left on the rootvnode
+ */
+ panic("(3) Unexpected pre-decrement value (%d) of usecount for rootvnode %p",
+ old_count, rootdir_with_usecount);
+ }
+ rootdir_with_usecount = NULLVP;
+ }
+ lck_rw_unlock_shared(rootvnode_rw_lock);
+ if (rootdir_with_usecount) {
+ vnode_rele(rootdir_with_usecount);
+ rootdir_with_usecount = NULLVP;
+ }
}
+
return 0;
}
continue_symlink:
/* Gives us a new path to process, and a starting dir */
- error = lookup_handle_symlink(ndp, &dp, ctx);
+ error = lookup_handle_symlink(ndp, &dp, &dp_has_iocount, ctx);
if (error != 0) {
break;
}
+ if (dp_has_iocount) {
+ if ((dp != rootdir_with_usecount) && (dp != startdir_with_usecount) &&
+ (dp != usedvp_dp)) {
+ if (startdir_with_usecount) {
+ vnode_rele(startdir_with_usecount);
+ }
+ vnode_ref_ext(dp, 0, VNODE_REF_FORCE);
+ startdir_with_usecount = dp;
+ }
+ vnode_put(dp);
+ dp_has_iocount = false;
+ }
}
/*
* only come here if we fail to handle a SYMLINK...
vnode_put(ndp->ni_vp);
}
error_out:
- if (proc_lock_taken) {
- proc_dirs_unlock_shared(p);
- proc_lock_taken = false;
+ if (startdir_with_usecount) {
+ vnode_rele(startdir_with_usecount);
+ startdir_with_usecount = NULLVP;
+ }
+ if (rootdir_with_usecount) {
+ lck_rw_lock_shared(rootvnode_rw_lock);
+ if (rootdir_with_usecount == rootvnode) {
+ old_count = os_atomic_dec_orig(&rootdir_with_usecount->v_usecount, relaxed);
+ if (old_count < 2) {
+ /*
+ * There needs to have been at least 1 usecount left on the rootvnode
+ */
+ panic("(4) Unexpected pre-decrement value (%d) of usecount for rootvnode %p",
+ old_count, rootdir_with_usecount);
+ }
+ lck_rw_unlock_shared(rootvnode_rw_lock);
+ } else {
+ lck_rw_unlock_shared(rootvnode_rw_lock);
+ vnode_rele(rootdir_with_usecount);
+ }
+ rootdir_with_usecount = NULLVP;
}
+
if ((cnp->cn_flags & HASBUF)) {
cnp->cn_flags &= ~HASBUF;
- FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
+ zfree(ZV_NAMEI, cnp->cn_pnbuf);
}
cnp->cn_pnbuf = NULL;
ndp->ni_vp = NULLVP;
{
char *path = NULL, *pp;
const char *name, *np;
- int len;
+ size_t len;
int error = 0;
struct nameidata nd;
vnode_t vp = dvp;
return 0;
}
- path = (char *) kalloc(MAXPATHLEN);
+ path = (char *) zalloc(ZV_NAMEI);
if (path == NULL) {
error = ENOMEM;
goto done;
goto done;
}
len = strlen(name);
- if ((len + 1) > (pp - path)) { // Enough space for this name ?
+ if ((len + 1) > (size_t)(pp - path)) { // Enough space for this name ?
error = ENAMETOOLONG;
vnode_putname(name);
goto done;
nameidone(&nd);
done:
if (path) {
- kfree(path, MAXPATHLEN);
+ zfree(ZV_NAMEI, path);
}
return error;
}
* at which to start a lookup with a resolved path, and all other iocounts dropped.
*/
static int
-lookup_handle_symlink(struct nameidata *ndp, vnode_t *new_dp, vfs_context_t ctx)
+lookup_handle_symlink(struct nameidata *ndp, vnode_t *new_dp, bool *new_dp_has_iocount, vfs_context_t ctx)
{
int error;
char *cp; /* pointer into pathname argument */
vnode_t dp;
char *tmppn;
u_int rsrclen = (cnp->cn_flags & CN_WANTSRSRCFORK) ? sizeof(_PATH_RSRCFORKSPEC) : 0;
+ bool dp_has_iocount = false;
if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
return ELOOP;
}
if (need_newpathbuf) {
- MALLOC_ZONE(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
- if (cp == NULL) {
- return ENOMEM;
- }
+ cp = zalloc(ZV_NAMEI);
} else {
cp = cnp->cn_pnbuf;
}
error = VNOP_READLINK(ndp->ni_vp, auio, ctx);
if (error) {
if (need_newpathbuf) {
- FREE_ZONE(cp, MAXPATHLEN, M_NAMEI);
+ zfree(ZV_NAMEI, cp);
}
return error;
}
linklen = MAXPATHLEN - (u_int)uio_resid(auio);
if (linklen + ndp->ni_pathlen + rsrclen > MAXPATHLEN) {
if (need_newpathbuf) {
- FREE_ZONE(cp, MAXPATHLEN, M_NAMEI);
+ zfree(ZV_NAMEI, cp);
}
return ENAMETOOLONG;
}
if (need_newpathbuf) {
- long len = cnp->cn_pnlen;
-
tmppn = cnp->cn_pnbuf;
bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
cnp->cn_pnbuf = cp;
cnp->cn_pnlen = MAXPATHLEN;
if ((cnp->cn_flags & HASBUF)) {
- FREE_ZONE(tmppn, len, M_NAMEI);
+ zfree(ZV_NAMEI, tmppn);
} else {
cnp->cn_flags |= HASBUF;
}
dp = ndp->ni_dvp;
/*
- * get rid of references returned via 'lookup'
+ * get rid of reference returned via 'lookup'
+ * ni_dvp is released only if we restart at /.
*/
vnode_put(ndp->ni_vp);
- vnode_put(ndp->ni_dvp); /* ALWAYS have a dvp for a symlink */
-
ndp->ni_vp = NULLVP;
ndp->ni_dvp = NULLVP;
* Check if symbolic link restarts us at the root
*/
if (*(cnp->cn_nameptr) == '/') {
+ vnode_put(dp); /* ALWAYS have a dvp for a symlink */
while (*(cnp->cn_nameptr) == '/') {
cnp->cn_nameptr++;
ndp->ni_pathlen--;
if ((dp = ndp->ni_rootdir) == NULLVP) {
return ENOENT;
}
+ } else {
+ dp_has_iocount = true;
}
*new_dp = dp;
+ *new_dp_has_iocount = dp_has_iocount;
return 0;
}
ndp->ni_cnd.cn_pnbuf = NULL;
ndp->ni_cnd.cn_flags &= ~HASBUF;
- FREE_ZONE(tmp, ndp->ni_cnd.cn_pnlen, M_NAMEI);
+ zfree(ZV_NAMEI, tmp);
}
}
/*
- * Log (part of) a pathname using the KERNEL_DEBUG_CONSTANT mechanism, as used
- * by fs_usage. The path up to and including the current component name are
- * logged. Up to NUMPARMS*4 bytes of pathname will be logged. If the path
- * to be logged is longer than that, then the last NUMPARMS*4 bytes are logged.
- * That is, the truncation removes the leading portion of the path.
- *
- * The logging is done via multiple KERNEL_DEBUG_CONSTANT calls. The first one
- * is marked with DBG_FUNC_START. The last one is marked with DBG_FUNC_END
- * (in addition to DBG_FUNC_START if it is also the first). There may be
- * intermediate ones with neither DBG_FUNC_START nor DBG_FUNC_END.
+ * Log (part of) a pathname using kdebug, as used by fs_usage. The path up to
+ * and including the current component name are logged. Up to NUMPARMS * 4
+ * bytes of pathname will be logged. If the path to be logged is longer than
+ * that, then the last NUMPARMS * 4 bytes are logged. That is, the truncation
+ * removes the leading portion of the path.
*
- * The first KERNEL_DEBUG_CONSTANT passes the vnode pointer and 12 bytes of
- * pathname. The remaining KERNEL_DEBUG_CONSTANT calls add 16 bytes of pathname
- * each. The minimum number of KERNEL_DEBUG_CONSTANT calls required to pass
- * the path are used. Any excess padding in the final KERNEL_DEBUG_CONSTANT
- * (because not all of the 12 or 16 bytes are needed for the remainder of the
- * path) is set to zero bytes, or '>' if there is more path beyond the
- * current component name (usually because an intermediate component was not
- * found).
+ * The logging is done via multiple KDBG_RELEASE calls. The first one is marked
+ * with DBG_FUNC_START. The last one is marked with DBG_FUNC_END (in addition
+ * to DBG_FUNC_START if it is also the first). There may be intermediate ones
+ * with neither DBG_FUNC_START nor DBG_FUNC_END.
*
- * NOTE: If the path length is greater than NUMPARMS*4, or is not of the form
- * 12+N*16, there will be no padding.
+ * The first event passes the vnode pointer and 24 or 32 (on K32, 12 or 24)
+ * bytes of pathname. The remaining events add 32 (on K32, 16) bytes of
+ * pathname each. The minimum number of events required to pass the path are
+ * used. Any excess padding in the final event (because not all of the 24 or 32
+ * (on K32, 12 or 16) bytes are needed for the remainder of the path) is set to
+ * zero bytes, or '>' if there is more path beyond the current component name
+ * (usually because an intermediate component was not found).
*
- * TODO: If there is more path beyond the current component name, should we
- * force some padding? For example, a lookup for /foo_bar_baz/spam that
- * fails because /foo_bar_baz is not found will only log "/foo_bar_baz", with
- * no '>' padding. But /foo_bar/spam would log "/foo_bar>>>>".
+ * NOTE: If the path length is greater than NUMPARMS * 4, or is not of the form
+ * 24 + N * 32 (or on K32, 12 + N * 16), there will be no padding.
*/
#if (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST)
void
-kdebug_vfs_lookup(long *dbg_parms, int dbg_namelen, void *dp, uint32_t flags)
+kdebug_vfs_lookup(unsigned long *path_words, int path_len, void *vnp,
+ uint32_t flags)
{
- int code;
- unsigned int i;
- bool lookup = flags & KDBG_VFS_LOOKUP_FLAG_LOOKUP;
bool noprocfilt = flags & KDBG_VFS_LOOKUP_FLAG_NOPROCFILT;
- /*
- * In the event that we collect multiple, consecutive pathname
- * entries, we must mark the start of the path's string and the end.
- */
- if (lookup) {
- code = VFS_LOOKUP | DBG_FUNC_START;
- } else {
- code = VFS_LOOKUP_DONE | DBG_FUNC_START;
- }
+ assert(path_len >= 0);
- if (dbg_namelen <= (int)(3 * sizeof(long))) {
+ int code = ((flags & KDBG_VFS_LOOKUP_FLAG_LOOKUP) ? VFS_LOOKUP :
+ VFS_LOOKUP_DONE) | DBG_FUNC_START;
+
+ if (path_len <= (3 * (int)sizeof(long))) {
code |= DBG_FUNC_END;
}
if (noprocfilt) {
- KDBG_RELEASE_NOPROCFILT(code, kdebug_vnode(dp), dbg_parms[0],
- dbg_parms[1], dbg_parms[2]);
+ KDBG_RELEASE_NOPROCFILT(code, kdebug_vnode(vnp), path_words[0],
+ path_words[1], path_words[2]);
} else {
- KDBG_RELEASE(code, kdebug_vnode(dp), dbg_parms[0], dbg_parms[1],
- dbg_parms[2]);
+ KDBG_RELEASE(code, kdebug_vnode(vnp), path_words[0], path_words[1],
+ path_words[2]);
}
code &= ~DBG_FUNC_START;
- for (i = 3, dbg_namelen -= (3 * sizeof(long)); dbg_namelen > 0; i += 4, dbg_namelen -= (4 * sizeof(long))) {
- if (dbg_namelen <= (int)(4 * sizeof(long))) {
+ for (int i = 3; i * (int)sizeof(long) < path_len; i += 4) {
+ if ((i + 4) * (int)sizeof(long) >= path_len) {
code |= DBG_FUNC_END;
}
if (noprocfilt) {
- KDBG_RELEASE_NOPROCFILT(code, dbg_parms[i], dbg_parms[i + 1],
- dbg_parms[i + 2], dbg_parms[i + 3]);
+ KDBG_RELEASE_NOPROCFILT(code, path_words[i], path_words[i + 1],
+ path_words[i + 2], path_words[i + 3]);
} else {
- KDBG_RELEASE(code, dbg_parms[i], dbg_parms[i + 1], dbg_parms[i + 2],
- dbg_parms[i + 3]);
+ KDBG_RELEASE(code, path_words[i], path_words[i + 1],
+ path_words[i + 2], path_words[i + 3]);
}
}
}
void
-kdebug_lookup_gen_events(long *dbg_parms, int dbg_namelen, void *dp,
- bool lookup)
+kdebug_lookup_gen_events(long *path_words, int path_len, void *vnp, bool lookup)
{
- kdebug_vfs_lookup(dbg_parms, dbg_namelen, dp,
+ assert(path_len >= 0);
+ kdebug_vfs_lookup((unsigned long *)path_words, path_len, vnp,
lookup ? KDBG_VFS_LOOKUP_FLAG_LOOKUP : 0);
}
void
-kdebug_lookup(vnode_t dp, struct componentname *cnp)
+kdebug_lookup(vnode_t vnp, struct componentname *cnp)
{
- int dbg_namelen;
- char *dbg_nameptr;
- long dbg_parms[NUMPARMS];
-
- /* Collect the pathname for tracing */
- dbg_namelen = (cnp->cn_nameptr - cnp->cn_pnbuf) + cnp->cn_namelen;
- dbg_nameptr = cnp->cn_nameptr + cnp->cn_namelen;
+ unsigned long path_words[NUMPARMS];
- if (dbg_namelen > (int)sizeof(dbg_parms)) {
- dbg_namelen = sizeof(dbg_parms);
- }
- dbg_nameptr -= dbg_namelen;
+ /*
+ * Truncate the leading portion of the path to fit in path_words.
+ */
+ char *path_end = cnp->cn_nameptr + cnp->cn_namelen;
+ size_t path_len = MIN(path_end - cnp->cn_pnbuf,
+ (ssize_t)sizeof(path_words));
+ assert(path_len >= 0);
+ char *path_trunc = path_end - path_len;
- /* Copy the (possibly truncated) path itself */
- memcpy(dbg_parms, dbg_nameptr, dbg_namelen);
+ memcpy(path_words, path_trunc, path_len);
- /* Pad with '\0' or '>' */
- if (dbg_namelen < (int)sizeof(dbg_parms)) {
- memset((char *)dbg_parms + dbg_namelen,
- *(cnp->cn_nameptr + cnp->cn_namelen) ? '>' : 0,
- sizeof(dbg_parms) - dbg_namelen);
+ /*
+ * Pad with '\0' or '>'.
+ */
+ if (path_len < (ssize_t)sizeof(path_words)) {
+ bool complete_str = *(cnp->cn_nameptr + cnp->cn_namelen) == '\0';
+ memset((char *)path_words + path_len, complete_str ? '\0' : '>',
+ sizeof(path_words) - path_len);
}
- kdebug_vfs_lookup(dbg_parms, dbg_namelen, (void *)dp,
- KDBG_VFS_LOOKUP_FLAG_LOOKUP);
+ kdebug_vfs_lookup(path_words, (int)path_len, vnp, KDBG_VFS_LOOKUP_FLAG_LOOKUP);
}
#else /* (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) */
struct mount *mp = NULL;
char *str;
char ch;
- uint32_t id;
+ unsigned long id;
ino64_t ino;
int error;
int length;
}
ch = *str;
- mp = mount_lookupby_volfsid(id, 1);
+ if (id > INT_MAX) {
+ return ENOENT;
+ }
+ mp = mount_lookupby_volfsid((int)id, 1);
if (mp == NULL) {
return EINVAL; /* unexpected failure */
}
realpath[0] = '\0';
/* Get the absolute path to this vnode. */
- error = build_path(vp, realpath, bufsize, &length, 0, ctx);
+ error = build_path(vp, realpath, (int)bufsize, &length, 0, ctx);
vnode_put(vp);
if (error == 0 && *str != '\0') {
- int attempt = strlcat(realpath, str, MAXPATHLEN);
+ size_t attempt = strlcat(realpath, str, MAXPATHLEN);
if (attempt > MAXPATHLEN) {
error = ENAMETOOLONG;
}