diff options
| -rw-r--r-- | sys/kern/init_sysent.c | 8 | ||||
| -rw-r--r-- | sys/kern/kern_pledge.c | 3 | ||||
| -rw-r--r-- | sys/kern/syscalls.c | 6 | ||||
| -rw-r--r-- | sys/kern/syscalls.master | 5 | ||||
| -rw-r--r-- | sys/kern/vfs_getcwd.c | 4 | ||||
| -rw-r--r-- | sys/kern/vfs_lookup.c | 60 | ||||
| -rw-r--r-- | sys/kern/vfs_syscalls.c | 91 | ||||
| -rw-r--r-- | sys/sys/namei.h | 7 | ||||
| -rw-r--r-- | sys/sys/syscall.h | 8 | ||||
| -rw-r--r-- | sys/sys/syscallargs.h | 10 |
10 files changed, 178 insertions, 24 deletions
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 79933937915..a6a4b2e283e 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -1,10 +1,10 @@ -/* $OpenBSD: init_sysent.c,v 1.201 2019/05/09 20:30:22 cheloha Exp $ */ +/* $OpenBSD: init_sysent.c,v 1.202 2019/05/13 22:55:27 beck Exp $ */ /* * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * created from; OpenBSD: syscalls.master,v 1.189 2019/01/11 18:46:30 deraadt Exp + * created from; OpenBSD: syscalls.master,v 1.190 2019/05/09 20:30:22 cheloha Exp */ #include <sys/param.h> @@ -262,8 +262,8 @@ struct sysent sysent[] = { sys_nosys }, /* 113 = unimplemented fktrace */ { 2, s(struct sys_unveil_args), 0, sys_unveil }, /* 114 = unveil */ - { 0, 0, 0, - sys_nosys }, /* 115 = obsolete vtrace */ + { 2, s(struct sys___realpath_args), 0, + sys___realpath }, /* 115 = __realpath */ { 0, 0, 0, sys_nosys }, /* 116 = obsolete t32_gettimeofday */ { 0, 0, 0, diff --git a/sys/kern/kern_pledge.c b/sys/kern/kern_pledge.c index 04ade838271..6c68e592122 100644 --- a/sys/kern/kern_pledge.c +++ b/sys/kern/kern_pledge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_pledge.c,v 1.251 2019/02/14 15:41:47 florian Exp $ */ +/* $OpenBSD: kern_pledge.c,v 1.252 2019/05/13 22:55:27 beck Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org> @@ -253,6 +253,7 @@ const uint64_t pledge_syscalls[SYS_MAXSYSCALL] = { [SYS_stat] = PLEDGE_STDIO, [SYS_access] = PLEDGE_STDIO, [SYS_readlink] = PLEDGE_STDIO, + [SYS___realpath] = PLEDGE_STDIO, /* XXX Fix me Theo! Fix me! */ [SYS_adjtime] = PLEDGE_STDIO, /* setting requires "settime" */ [SYS_adjfreq] = PLEDGE_SETTIME, diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 2acf552dfc5..b6fc8fc6d5e 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -1,10 +1,10 @@ -/* $OpenBSD: syscalls.c,v 1.200 2019/05/09 20:30:22 cheloha Exp $ */ +/* $OpenBSD: syscalls.c,v 1.201 2019/05/13 22:55:27 beck Exp $ */ /* * System call names. * * DO NOT EDIT-- this file is automatically generated. - * created from; OpenBSD: syscalls.master,v 1.189 2019/01/11 18:46:30 deraadt Exp + * created from; OpenBSD: syscalls.master,v 1.190 2019/05/09 20:30:22 cheloha Exp */ char *syscallnames[] = { @@ -135,7 +135,7 @@ char *syscallnames[] = { "sendsyslog", /* 112 = sendsyslog */ "#113 (unimplemented fktrace)", /* 113 = unimplemented fktrace */ "unveil", /* 114 = unveil */ - "#115 (obsolete vtrace)", /* 115 = obsolete vtrace */ + "__realpath", /* 115 = __realpath */ "#116 (obsolete t32_gettimeofday)", /* 116 = obsolete t32_gettimeofday */ "#117 (obsolete t32_getrusage)", /* 117 = obsolete t32_getrusage */ "getsockopt", /* 118 = getsockopt */ diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 8474448d844..8c6ea62e801 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -1,4 +1,4 @@ -; $OpenBSD: syscalls.master,v 1.190 2019/05/09 20:30:22 cheloha Exp $ +; $OpenBSD: syscalls.master,v 1.191 2019/05/13 22:55:27 beck Exp $ ; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $ ; @(#)syscalls.master 8.2 (Berkeley) 1/13/94 @@ -240,7 +240,8 @@ 113 UNIMPL fktrace 114 STD { int sys_unveil(const char *path, \ const char *permissions); } -115 OBSOL vtrace +115 STD { int sys___realpath(const char *pathname, \ + char *resolved); } 116 OBSOL t32_gettimeofday 117 OBSOL t32_getrusage 118 STD { int sys_getsockopt(int s, int level, int name, \ diff --git a/sys/kern/vfs_getcwd.c b/sys/kern/vfs_getcwd.c index 4e04ceb0925..2707c1dcdde 100644 --- a/sys/kern/vfs_getcwd.c +++ b/sys/kern/vfs_getcwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_getcwd.c,v 1.31 2018/05/27 06:02:14 visa Exp $ */ +/* $OpenBSD: vfs_getcwd.c,v 1.32 2019/05/13 22:55:27 beck Exp $ */ /* $NetBSD: vfs_getcwd.c,v 1.3.2.3 1999/07/11 10:24:09 sommerfeld Exp $ */ /* @@ -265,7 +265,7 @@ vfs_getcwd_getcache(struct vnode **lvpp, struct vnode **uvpp, char **bpp, return (error); } -/* Common routine shared by sys___getcwd() and vn_isunder() */ +/* Common routine shared by sys___getcwd() and vn_isunder() and sys___realpath() */ int vfs_getcwd_common(struct vnode *lvp, struct vnode *rvp, char **bpp, char *bufp, int limit, int flags, struct proc *p) diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index e9637a7f3e4..a57f6f99915 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_lookup.c,v 1.76 2019/01/03 21:52:31 beck Exp $ */ +/* $OpenBSD: vfs_lookup.c,v 1.77 2019/05/13 22:55:27 beck Exp $ */ /* $NetBSD: vfs_lookup.c,v 1.17 1996/02/09 19:00:59 christos Exp $ */ /* @@ -61,6 +61,29 @@ void unveil_start_relative(struct proc *p, struct nameidata *ni); void unveil_check_component(struct proc *p, struct nameidata *ni, struct vnode *dp ); int unveil_check_final(struct proc *p, struct nameidata *ni); +int +component_push(struct componentname *cnp, char *component, size_t len) +{ + if (cnp->cn_rpi + len + 1 >= MAXPATHLEN) + return 0; + if (cnp->cn_rpi > 1) + cnp->cn_rpbuf[cnp->cn_rpi++] = '/'; + memcpy(cnp->cn_rpbuf + cnp->cn_rpi, component, len); + cnp->cn_rpi+=len; + cnp->cn_rpbuf[cnp->cn_rpi] = '\0'; + return 1; +} + +void +component_pop(struct componentname *cnp) +{ + while(cnp->cn_rpi && cnp->cn_rpbuf[cnp->cn_rpi] != '/' ) + cnp->cn_rpi--; + if (cnp->cn_rpi == 0 && cnp->cn_rpbuf[0] == '/') + cnp->cn_rpi++; + cnp->cn_rpbuf[cnp->cn_rpi] = '\0'; +} + void ndinitat(struct nameidata *ndp, u_long op, u_long flags, enum uio_seg segflg, int dirfd, const char *namep, struct proc *p) @@ -190,6 +213,11 @@ fail: if (cnp->cn_pnbuf[0] == '/') { dp = ndp->ni_rootdir; vref(dp); + if (cnp->cn_flags & REALPATH && cnp->cn_rpi == 0) { + cnp->cn_rpbuf[0] = '/'; + cnp->cn_rpbuf[1] = '\0'; + cnp->cn_rpi = 1; + } } else if (ndp->ni_dirfd == AT_FDCWD) { dp = fdp->fd_cdir; vref(dp); @@ -303,6 +331,13 @@ badlink: vref(dp); ndp->ni_unveil_match = NULL; unveil_check_component(p, ndp, dp); + if (cnp->cn_flags & REALPATH) { + cnp->cn_rpbuf[0] = '/'; + cnp->cn_rpbuf[1] = '\0'; + cnp->cn_rpi = 1; + } + } else if (cnp->cn_flags & REALPATH) { + component_pop(cnp); } } pool_put(&namei_pool, cnp->cn_pnbuf); @@ -441,6 +476,19 @@ dirloop: printf("{%s}: ", cnp->cn_nameptr); *cp = c; } #endif + if (cnp->cn_flags & REALPATH) { + size_t len = cp - cnp->cn_nameptr; + if (len == 2 && cnp->cn_nameptr[0] == '.' && + cnp->cn_nameptr[1] == '.') + component_pop(cnp); + else if (!(len == 1 && cnp->cn_nameptr[0] == '.')) { + if (!component_push(cnp, cnp->cn_nameptr, len)) { + error = ENAMETOOLONG; + goto bad; + } + } + } + ndp->ni_pathlen -= cnp->cn_namelen; ndp->ni_next = cp; /* @@ -529,10 +577,12 @@ dirloop: printf("not found\n"); #endif /* - * Allow for unveiling of a file in a directory - * where we don't have access to create it ourselves + * Allow for unveiling or realpath'ing a file in a + * directory where we don't have access to create it + * ourselves */ - if (ndp->ni_pledge == PLEDGE_UNVEIL && error == EACCES) + if ((ndp->ni_pledge == PLEDGE_UNVEIL || + (cnp->cn_flags & REALPATH)) && error == EACCES) error = EJUSTRETURN; if (error != EJUSTRETURN) @@ -808,3 +858,5 @@ bad: *vpp = NULL; return (error); } + + diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index be31bc6229c..5b649af01d7 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.314 2019/03/24 18:14:20 beck Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.315 2019/05/13 22:55:27 beck Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -868,6 +868,95 @@ change_dir(struct nameidata *ndp, struct proc *p) } int +sys___realpath(struct proc *p, void *v, register_t *retval) +{ + struct sys___realpath_args /* { + syscallarg(const char *) pathname; + syscallarg(char *) resolved; + } */ *uap = v; + char *pathname; + char *cwdbuf; + char *rpbuf; + struct nameidata nd; + size_t pathlen; + int cwdlen = MAXPATHLEN * 4; + int error = 0; + + pathname = pool_get(&namei_pool, PR_WAITOK); + rpbuf = pool_get(&namei_pool, PR_WAITOK); + cwdbuf = malloc(cwdlen, M_TEMP, M_WAITOK); + + if ((error = copyinstr(SCARG(uap, pathname), pathname, MAXPATHLEN, + &pathlen))) + goto end; + + if (pathlen < 2) { + error = EINVAL; + goto end; + } + + /* Get cwd for relative path if needed, prepend to rpbuf */ + rpbuf[0] = '\0'; + if (pathname[0] != '/') { + char *path, *bp, *bend; + int lenused; + + bp = &cwdbuf[cwdlen]; + bend = bp; + *(--bp) = '\0'; + + error = vfs_getcwd_common(p->p_fd->fd_cdir, NULL, &bp, path, + cwdlen/2, GETCWD_CHECK_ACCESS, p); + + if (error) + goto end; + + lenused = bend - bp; + *retval = lenused; + + if (strlcpy(rpbuf, bp, MAXPATHLEN) >= MAXPATHLEN) { + error = ENAMETOOLONG; + goto end; + } + } + + if (pathlen == 2 && pathname[0] == '/') + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME | REALPATH, + UIO_SYSSPACE, pathname, p); + else + NDINIT(&nd, CREATE, FOLLOW | LOCKLEAF | LOCKPARENT | SAVENAME | + REALPATH, UIO_SYSSPACE, pathname, p); + + nd.ni_cnd.cn_rpbuf = rpbuf; + nd.ni_cnd.cn_rpi = strlen(rpbuf); + + nd.ni_pledge = PLEDGE_RPATH; + nd.ni_unveil = UNVEIL_READ; + if ((error = namei(&nd)) != 0) + goto end; + + /* release lock and reference from namei */ + if (nd.ni_vp) { + VOP_UNLOCK(nd.ni_vp); + vrele(nd.ni_vp); + } + if (nd.ni_dvp && nd.ni_dvp != nd.ni_vp){ + VOP_UNLOCK(nd.ni_dvp); + vrele(nd.ni_dvp); + } + + error = copyoutstr(nd.ni_cnd.cn_rpbuf, SCARG(uap, resolved), + MAXPATHLEN, NULL); + + pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf); +end: + pool_put(&namei_pool, rpbuf); + pool_put(&namei_pool, pathname); + free(cwdbuf, M_TEMP, cwdlen); + return (error); +} + +int sys_unveil(struct proc *p, void *v, register_t *retval) { struct sys_unveil_args /* { diff --git a/sys/sys/namei.h b/sys/sys/namei.h index aea0e511212..535a219603a 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -1,4 +1,4 @@ -/* $OpenBSD: namei.h,v 1.39 2019/01/17 03:26:19 beck Exp $ */ +/* $OpenBSD: namei.h,v 1.40 2019/05/13 22:55:27 beck Exp $ */ /* $NetBSD: namei.h,v 1.11 1996/02/09 18:25:20 christos Exp $ */ /* @@ -80,7 +80,7 @@ struct nameidata { /* * Lookup parameters: this structure describes the subset of - * information from the nameidata structure that is passed + * information from the nameidat satructure that is passed * through the VOP interface. */ struct componentname { @@ -95,6 +95,8 @@ struct nameidata { * Shared between lookup and commit routines. */ char *cn_pnbuf; /* pathname buffer */ + char *cn_rpbuf; /* realpath buffer */ + size_t cn_rpi; /* realpath index */ char *cn_nameptr; /* pointer to looked up name */ long cn_namelen; /* length of looked up component */ long cn_consume; /* chars to consume in lookup() */ @@ -143,6 +145,7 @@ struct nameidata { #define MAKEENTRY 0x004000 /* entry is to be added to name cache */ #define ISLASTCN 0x008000 /* this is last component of pathname */ #define ISSYMLINK 0x010000 /* symlink needs interpretation */ +#define REALPATH 0x020000 /* save pathname buffer for realpath */ #define REQUIREDIR 0x080000 /* must be a directory */ #define STRIPSLASHES 0x100000 /* strip trailing slashes */ #define PDIRUNLOCK 0x200000 /* vfs_lookup() unlocked parent dir */ diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index abbaf6eb647..2e6d31d731e 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -1,10 +1,10 @@ -/* $OpenBSD: syscall.h,v 1.200 2019/01/11 18:52:41 deraadt Exp $ */ +/* $OpenBSD: syscall.h,v 1.201 2019/05/13 22:55:27 beck Exp $ */ /* * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * created from; OpenBSD: syscalls.master,v 1.189 2019/01/11 18:46:30 deraadt Exp + * created from; OpenBSD: syscalls.master,v 1.190 2019/05/09 20:30:22 cheloha Exp */ /* syscall: "syscall" ret: "int" args: "int" "..." */ @@ -342,7 +342,9 @@ /* syscall: "unveil" ret: "int" args: "const char *" "const char *" */ #define SYS_unveil 114 - /* 115 is obsolete vtrace */ +/* syscall: "__realpath" ret: "int" args: "const char *" "char *" */ +#define SYS___realpath 115 + /* 116 is obsolete t32_gettimeofday */ /* 117 is obsolete t32_getrusage */ /* syscall: "getsockopt" ret: "int" args: "int" "int" "int" "void *" "socklen_t *" */ diff --git a/sys/sys/syscallargs.h b/sys/sys/syscallargs.h index ebe0ec9212f..532e51b596e 100644 --- a/sys/sys/syscallargs.h +++ b/sys/sys/syscallargs.h @@ -1,10 +1,10 @@ -/* $OpenBSD: syscallargs.h,v 1.203 2019/01/11 18:52:41 deraadt Exp $ */ +/* $OpenBSD: syscallargs.h,v 1.204 2019/05/13 22:55:27 beck Exp $ */ /* * System call argument lists. * * DO NOT EDIT-- this file is automatically generated. - * created from; OpenBSD: syscalls.master,v 1.189 2019/01/11 18:46:30 deraadt Exp + * created from; OpenBSD: syscalls.master,v 1.190 2019/05/09 20:30:22 cheloha Exp */ #ifdef syscallarg @@ -567,6 +567,11 @@ struct sys_unveil_args { syscallarg(const char *) permissions; }; +struct sys___realpath_args { + syscallarg(const char *) pathname; + syscallarg(char *) resolved; +}; + struct sys_getsockopt_args { syscallarg(int) s; syscallarg(int) level; @@ -1218,6 +1223,7 @@ int sys_pselect(struct proc *, void *, register_t *); int sys_sigsuspend(struct proc *, void *, register_t *); int sys_sendsyslog(struct proc *, void *, register_t *); int sys_unveil(struct proc *, void *, register_t *); +int sys___realpath(struct proc *, void *, register_t *); int sys_getsockopt(struct proc *, void *, register_t *); int sys_thrkill(struct proc *, void *, register_t *); int sys_readv(struct proc *, void *, register_t *); |
