summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/init_sysent.c8
-rw-r--r--sys/kern/kern_pledge.c3
-rw-r--r--sys/kern/syscalls.c6
-rw-r--r--sys/kern/syscalls.master5
-rw-r--r--sys/kern/vfs_getcwd.c4
-rw-r--r--sys/kern/vfs_lookup.c60
-rw-r--r--sys/kern/vfs_syscalls.c91
-rw-r--r--sys/sys/namei.h7
-rw-r--r--sys/sys/syscall.h8
-rw-r--r--sys/sys/syscallargs.h10
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 *);