Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160210206
D23574.id67952.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D23574.id67952.diff
View Options
Index: lib/libc/stdlib/realpath.c
===================================================================
--- lib/libc/stdlib/realpath.c
+++ lib/libc/stdlib/realpath.c
@@ -44,12 +44,14 @@
#include <unistd.h>
#include "un-namespace.h"
+extern int __realpath(const char *path, char *buf, size_t size, int flags);
+
/*
* Find the real name of path, by removing all ".", ".." and symlink
* components. Returns (resolved) on success, or (NULL) on failure,
* in which case the path which caused trouble is left in (resolved).
*/
-static char *
+static char * __noinline
realpath1(const char *path, char *resolved)
{
struct stat sb;
@@ -223,6 +225,8 @@
if (resolved == NULL)
return (NULL);
}
+ if (__realpath(path, resolved, PATH_MAX, 0) == 0)
+ return (resolved);
res = realpath1(path, resolved);
if (res == NULL)
free(m);
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map
+++ lib/libc/sys/Symbol.map
@@ -402,6 +402,7 @@
};
FBSD_1.6 {
+ __realpath;
__sysctlbyname;
copy_file_range;
fhlink;
Index: sys/bsm/audit_kevents.h
===================================================================
--- sys/bsm/audit_kevents.h
+++ sys/bsm/audit_kevents.h
@@ -657,6 +657,7 @@
#define AUE_LGETUUID 43261 /* CADETS. */
#define AUE_EXECVEAT 43262 /* FreeBSD/Linux. */
#define AUE_SHMRENAME 43263 /* FreeBSD-specific. */
+#define AUE_REALPATH 43264 /* FreeBSD-specific. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -1159,5 +1159,7 @@
int shmflags, const char *name); }
572 AUE_SHMRENAME NOPROTO { int shm_rename(const char *path_from, \
const char *path_to, int flags); }
+573 AUE_REALPATH NOPROTO { int __realpath(const char *path, char *buf, \
+ size_t size, int flags); }
; vim: syntax=off
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master
+++ sys/kern/syscalls.master
@@ -3212,6 +3212,14 @@
int flags
);
}
+573 AUE_REALPATH STD {
+ int __realpath(
+ _In_z_ const char *path,
+ _In_z_ char *buf,
+ size_t size,
+ int flags
+ );
+ }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/kern/vfs_cache.c
===================================================================
--- sys/kern/vfs_cache.c
+++ sys/kern/vfs_cache.c
@@ -42,6 +42,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capsicum.h>
#include <sys/counter.h>
#include <sys/filedesc.h>
#include <sys/fnv_hash.h>
@@ -387,8 +388,12 @@
"Number of times shrinking was already in progress");
static void cache_zap_locked(struct namecache *ncp, bool neg_locked);
-static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
+static int vn_fullpath_hardlink(struct thread *td, struct nameidata *ndp, char **retbuf,
+ char **freebuf, size_t *buflen);
+static int vn_fullpath_any(struct thread *td, struct vnode *vp, struct vnode *rdir,
char *buf, char **retbuf, size_t *buflen);
+static int vn_fullpath_dir(struct thread *td, struct vnode *vp, struct vnode *rdir,
+ char *buf, char **retbuf, size_t *len, int slash_prefixed, size_t addend);
static MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries");
@@ -2201,7 +2206,7 @@
rdir = fdp->fd_rdir;
vrefact(rdir);
FILEDESC_SUNLOCK(fdp);
- error = vn_fullpath1(td, cdir, rdir, buf, retbuf, buflen);
+ error = vn_fullpath_any(td, cdir, rdir, buf, retbuf, buflen);
vrele(rdir);
vrele(cdir);
@@ -2212,6 +2217,41 @@
return (error);
}
+
+
+static int
+kern___realpath(struct thread *td, const char *path, char *buf, size_t size,
+ int flags, enum uio_seg pathseg)
+{
+ struct nameidata nd;
+ char *retbuf, *freebuf;
+ int error;
+
+ if (flags != 0)
+ return (EINVAL);
+
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | SAVENAME | WANTPARENT | AUDITVNODE1,
+ pathseg, path, AT_FDCWD, &cap_fstat_rights, td);
+ if ((error = namei(&nd)) != 0)
+ return (error);
+ error = vn_fullpath_hardlink(td, &nd, &retbuf, &freebuf, &size);
+ if (error == 0) {
+ error = copyout(retbuf, buf, size);
+ free(freebuf, M_TEMP);
+ }
+ NDFREE(&nd, 0);
+
+ return (error);
+}
+
+int
+sys___realpath(struct thread *td, struct __realpath_args *uap)
+{
+
+ return (kern___realpath(td, uap->path, uap->buf, uap->size, uap->flags,
+ UIO_USERSPACE));
+}
+
/*
* Retrieve the full filesystem path that correspond to a vnode from the name
* cache (if available)
@@ -2235,7 +2275,7 @@
rdir = fdp->fd_rdir;
vrefact(rdir);
FILEDESC_SUNLOCK(fdp);
- error = vn_fullpath1(td, vn, rdir, buf, retbuf, &buflen);
+ error = vn_fullpath_any(td, vn, rdir, buf, retbuf, &buflen);
vrele(rdir);
if (!error)
@@ -2263,7 +2303,7 @@
return (EINVAL);
buflen = MAXPATHLEN;
buf = malloc(buflen, M_TEMP, M_WAITOK);
- error = vn_fullpath1(td, vn, rootvnode, buf, retbuf, &buflen);
+ error = vn_fullpath_any(td, vn, rootvnode, buf, retbuf, &buflen);
if (!error)
*freebuf = buf;
else
@@ -2333,41 +2373,30 @@
return (0);
}
-/*
- * The magic behind vn_getcwd() and vn_fullpath().
- */
static int
-vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
- char *buf, char **retbuf, size_t *len)
+vn_fullpath_dir(struct thread *td, struct vnode *vp, struct vnode *rdir,
+ char *buf, char **retbuf, size_t *len, int slash_prefixed, size_t addend)
{
- int error, slash_prefixed;
#ifdef KDTRACE_HOOKS
struct vnode *startvp = vp;
#endif
struct vnode *vp1;
size_t buflen;
+ int error;
+
+ VNPASS(vp->v_type == VDIR || VN_IS_DOOMED(vp), vp);
buflen = *len;
- buflen--;
- buf[buflen] = '\0';
+ if (!slash_prefixed) {
+ buflen--;
+ buf[buflen] = '\0';
+ }
+
error = 0;
- slash_prefixed = 0;
SDT_PROBE1(vfs, namecache, fullpath, entry, vp);
counter_u64_add(numfullpathcalls, 1);
- vref(vp);
- if (vp->v_type != VDIR) {
- error = vn_vptocnp(&vp, td->td_ucred, buf, &buflen);
- if (error)
- return (error);
- if (buflen == 0) {
- vrele(vp);
- return (ENOMEM);
- }
- buf[--buflen] = '/';
- slash_prefixed = 1;
- }
while (vp != rdir && vp != rootvnode) {
/*
* The vp vnode must be already fully constructed,
@@ -2437,12 +2466,101 @@
counter_u64_add(numfullpathfound, 1);
vrele(vp);
- SDT_PROBE3(vfs, namecache, fullpath, return, 0, startvp, buf + buflen);
*retbuf = buf + buflen;
+ SDT_PROBE3(vfs, namecache, fullpath, return, 0, startvp, *retbuf);
*len -= buflen;
+ *len += addend;
return (0);
}
+static int
+vn_fullpath_any(struct thread *td, struct vnode *vp, struct vnode *rdir,
+ char *buf, char **retbuf, size_t *len)
+{
+ size_t orig_len = *len;
+ int slash_prefixed;
+ int error;
+
+ vref(vp);
+ slash_prefixed = 0;
+ if (vp->v_type != VDIR) {
+ *len -= 1;
+ buf[*len] = '\0';
+ error = vn_vptocnp(&vp, td->td_ucred, buf, len);
+ if (error)
+ return (error);
+ if (*len == 0) {
+ vrele(vp);
+ return (ENOMEM);
+ }
+ *len -= 1;
+ buf[*len] = '/';
+ slash_prefixed = 1;
+ }
+
+ return (vn_fullpath_dir(td, vp, rdir, buf, retbuf, len, slash_prefixed, orig_len - *len));
+}
+
+static int
+vn_fullpath_hardlink(struct thread *td, struct nameidata *ndp, char **retbuf,
+ char **freebuf, size_t *buflen)
+{
+ char *buf, *tmpbuf;
+ struct filedesc *fdp;
+ struct vnode *rdir;
+ struct componentname *cnp;
+ struct vnode *vp;
+ int error, slash_prefixed;
+ size_t addend;
+
+ if (*buflen < 2)
+ return (EINVAL);
+ if (*buflen > MAXPATHLEN)
+ *buflen = MAXPATHLEN;
+
+ slash_prefixed = 0;
+
+ buf = malloc(*buflen, M_TEMP, M_WAITOK);
+ fdp = td->td_proc->p_fd;
+ FILEDESC_SLOCK(fdp);
+ rdir = fdp->fd_rdir;
+ vrefact(rdir);
+ FILEDESC_SUNLOCK(fdp);
+
+ *freebuf = buf;
+
+ addend = 0;
+ vp = ndp->ni_vp;
+ if (vp->v_type != VDIR) {
+ cnp = &ndp->ni_cnd;
+ addend = cnp->cn_namelen + 2;
+ if (*buflen < addend) {
+ error = ENOMEM;
+ goto out_bad;
+ }
+ *buflen -= addend;
+ tmpbuf = buf + *buflen;
+ tmpbuf[0] = '/';
+ memcpy(&tmpbuf[1], cnp->cn_nameptr, cnp->cn_namelen);
+ tmpbuf[addend - 1] = '\0';
+ slash_prefixed = 1;
+ vp = ndp->ni_dvp;
+ }
+
+ vref(vp);
+ error = vn_fullpath_dir(td, vp, rdir, buf, retbuf, buflen, slash_prefixed, addend);
+ if (error != 0)
+ goto out_bad;
+
+ vrele(rdir);
+
+ return (0);
+out_bad:
+ vrele(rdir);
+ free(buf, M_TEMP);
+ return (error);
+}
+
struct vnode *
vn_dir_dd_ino(struct vnode *vp)
{
Index: sys/security/audit/audit_bsm.c
===================================================================
--- sys/security/audit/audit_bsm.c
+++ sys/security/audit/audit_bsm.c
@@ -737,6 +737,7 @@
audit_sys_auditon(ar, rec);
break;
+ case AUE_REALPATH:
case AUE_AUDITCTL:
UPATH1_VNODE1_TOKENS;
break;
Index: usr.bin/truss/syscalls.c
===================================================================
--- usr.bin/truss/syscalls.c
+++ usr.bin/truss/syscalls.c
@@ -115,6 +115,8 @@
.args = { { Int, 0 }, { Int, 1 }, { CapRights | OUT, 2 } } },
{ .name = "__getcwd", .ret_type = 1, .nargs = 2,
.args = { { Name | OUT, 0 }, { Int, 1 } } },
+ { .name = "__realpath", .ret_type = 1, .nargs = 4,
+ .args = { { Name | IN, 0 }, { Name | OUT, 1 }, { Sizet, 2 }, { Int, 3} } },
{ .name = "_umtx_op", .ret_type = 1, .nargs = 5,
.args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 },
{ Ptr, 4 } } },
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jun 23, 5:14 AM (18 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34231602
Default Alt Text
D23574.id67952.diff (9 KB)
Attached To
Mode
D23574: vfs: add kernel-side realpathat
Attached
Detach File
Event Timeline
Log In to Comment