-/* $OpenBSD: kern_unveil.c,v 1.10 2018/08/05 13:59:38 beck Exp $ */
+/* $OpenBSD: kern_unveil.c,v 1.11 2018/08/05 14:23:57 beck Exp $ */
/*
* Copyright (c) 2017-2018 Bob Beck <beck@openbsd.org>
#define UNVEIL_MAX_VNODES 128
#define UNVEIL_MAX_NAMES 128
+#define UNVEIL_READ 0x01
+#define UNVEIL_WRITE 0x02
+#define UNVEIL_CREATE 0x04
+#define UNVEIL_EXEC 0x08
+
static inline int
unvname_compare(const struct unvname *n1, const struct unvname *n2)
{
}
struct unvname *
-unvname_new(const char *name, size_t size, uint64_t flags)
+unvname_new(const char *name, size_t size, u_char flags)
{
struct unvname *ret = malloc(sizeof(struct unvname), M_PROC, M_WAITOK);
ret->un_name = malloc(size, M_PROC, M_WAITOK);
}
void
-unveil_add_name(struct unveil *uv, char *name, uint64_t flags)
+unveil_add_name(struct unveil *uv, char *name, u_char flags)
{
struct unvname *unvn;
}
int
-unveil_parsepermissions(const char *permissions, uint64_t *perms)
+unveil_parsepermissions(const char *permissions, u_char *perms)
{
size_t i = 0;
char c;
while ((c = permissions[i++]) != '\0') {
switch (c) {
case 'r':
- *perms |= PLEDGE_RPATH;
+ *perms |= UNVEIL_READ;
break;
case 'w':
- *perms |= PLEDGE_WPATH;
+ *perms |= UNVEIL_WRITE;
break;
case 'x':
- *perms |= PLEDGE_EXEC;
+ *perms |= UNVEIL_EXEC;
break;
case 'c':
- *perms |= PLEDGE_CPATH;
+ *perms |= UNVEIL_CREATE;
break;
default:
return -1;
}
int
-unveil_setflags(uint64_t *flags, uint64_t nflags)
+unveil_setflags(u_char *flags, u_char nflags)
{
#if 0
if (((~(*flags)) & nflags) != 0) {
struct unveil *uv;
int directory_add;
int ret = EINVAL;
- u_int64_t flags;
+ u_char flags;
KASSERT(ISSET(ndp->ni_cnd.cn_flags, HASBUF)); /* must have SAVENAME */
* XXX collapse down later once debug surely unneded
*/
int
-unveil_flagmatch(struct nameidata *ni, uint64_t flags)
+unveil_flagmatch(struct nameidata *ni, u_char flags)
{
if (flags == 0) {
+ /* XXX Fix this, you can do it better */
if (ni->ni_pledge & PLEDGE_STAT) {
#ifdef DEBUG_UNVEIL
printf("allowing stat/accesss for 0 flags");
CLR(ni->ni_pledge, PLEDGE_STATLIE);
return 1;
}
- if (ni->ni_pledge & PLEDGE_RPATH) {
- if ((flags & PLEDGE_RPATH) == 0) {
+ if (ni->ni_unveil & UNVEIL_READ) {
+ if ((flags & UNVEIL_READ) == 0) {
#ifdef DEBUG_UNVEIL
- printf("Pledge wants read but disallowed\n");
+ printf("unveil lacks UNVEIL_READ\n");
#endif
return 0;
}
}
- if (ni->ni_pledge & PLEDGE_WPATH) {
- if ((flags & PLEDGE_WPATH) == 0) {
+ if (ni->ni_unveil & UNVEIL_WRITE) {
+ if ((flags & UNVEIL_WRITE) == 0) {
#ifdef DEBUG_UNVEIL
- printf("Pledge wants write but disallowed\n");
+ printf("unveil lacks UNVEIL_WRITE\n");
#endif
return 0;
}
}
- if (ni->ni_pledge & PLEDGE_EXEC) {
- if ((flags & PLEDGE_EXEC) == 0) {
+ if (ni->ni_unveil & UNVEIL_EXEC) {
+ if ((flags & UNVEIL_EXEC) == 0) {
#ifdef DEBUG_UNVEIL
- printf("Pledge wants exec but disallowed\n");
+ printf("unveil lacks UNVEIL_EXEC\n");
#endif
return 0;
}
}
- if (ni->ni_pledge & PLEDGE_CPATH) {
- if ((flags & PLEDGE_CPATH) == 0) {
+ if (ni->ni_unveil & UNVEIL_CREATE) {
+ if ((flags & UNVEIL_CREATE) == 0) {
#ifdef DEBUG_UNVEIL
- printf("Pledge wants cpath but disallowed\n");
+ printf("unveil lacks UNVEIL_CREATE\n");
#endif
return 0;
}
-/* $OpenBSD: vfs_syscalls.c,v 1.300 2018/08/03 02:36:11 beck Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.301 2018/08/05 14:23:57 beck Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
nd.ni_pledge = PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_READ;
nd.ni_cnd.cn_flags |= BYPASSUNVEIL;
if ((error = namei(&nd)) != 0)
return (error);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
SCARG(uap, path), p);
nd.ni_pledge = PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_READ;
if ((error = change_dir(&nd, p)) != 0)
return (error);
p->p_p->ps_uvpcwd = nd.ni_unveil_match;
struct flock lf;
struct nameidata nd;
uint64_t ni_pledge = 0;
+ u_char ni_unveil = 0;
if (oflags & (O_EXLOCK | O_SHLOCK)) {
error = pledge_flock(p);
fdpunlock(fdp);
flags = FFLAGS(oflags);
- if (flags & FREAD)
+ if (flags & FREAD) {
ni_pledge |= PLEDGE_RPATH;
- if (flags & FWRITE)
+ ni_unveil |= UNVEIL_READ;
+ }
+ if (flags & FWRITE) {
ni_pledge |= PLEDGE_WPATH;
- if (oflags & O_CREAT)
+ ni_unveil |= UNVEIL_WRITE;
+ }
+ if (oflags & O_CREAT) {
ni_pledge |= PLEDGE_CPATH;
+ ni_unveil |= UNVEIL_CREATE;
+ }
cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
if ((p->p_p->ps_flags & PS_PLEDGE))
cmode &= ACCESSPERMS;
NDINITAT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, fd, path, p);
nd.ni_pledge = ni_pledge;
+ nd.ni_unveil = ni_unveil;
p->p_dupfd = -1; /* XXX check for fdopen */
if ((flags & O_TRUNC) && (flags & (O_EXLOCK | O_SHLOCK))) {
localtrunc = 1;
return (EINVAL);
NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd, path, p);
nd.ni_pledge = PLEDGE_DPATH;
+ nd.ni_unveil = UNVEIL_CREATE;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
follow = (flag & AT_SYMLINK_FOLLOW) ? FOLLOW : NOFOLLOW;
NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd1, path1, p);
nd.ni_pledge = PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_READ;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
NDINITAT(&nd, CREATE, flags, UIO_USERSPACE, fd2, path2, p);
nd.ni_pledge = PLEDGE_CPATH;
+ nd.ni_unveil = UNVEIL_CREATE;
if ((error = namei(&nd)) != 0)
goto out;
if (nd.ni_vp) {
goto out;
NDINITAT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, fd, link, p);
nd.ni_pledge = PLEDGE_CPATH;
+ nd.ni_unveil = UNVEIL_CREATE;
if ((error = namei(&nd)) != 0)
goto out;
if (nd.ni_vp) {
NDINITAT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
fd, path, p);
nd.ni_pledge = PLEDGE_CPATH;
+ nd.ni_unveil = UNVEIL_CREATE;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
NDINITAT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, fd, path, p);
nd.ni_pledge = PLEDGE_RPATH | PLEDGE_STAT;
+ nd.ni_unveil = 0; /* XXX fix this when we fix PLEDGE_STAT */
if ((error = namei(&nd)) != 0)
goto out;
vp = nd.ni_vp;
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
NDINITAT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fd, path, p);
nd.ni_pledge = PLEDGE_RPATH | PLEDGE_STAT;
+ nd.ni_unveil = 0;
if ((error = namei(&nd)) != 0)
return (error);
error = vn_stat(nd.ni_vp, &sb, p);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
SCARG(uap, path), p);
nd.ni_pledge = PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_READ;
if ((error = namei(&nd)) != 0)
return (error);
error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
NDINITAT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, fd, path, p);
nd.ni_pledge = PLEDGE_RPATH | PLEDGE_STAT;
+ nd.ni_unveil = 0;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
follow = (atflags & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p);
nd.ni_pledge = PLEDGE_FATTR | PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_WRITE;
if ((error = namei(&nd)) != 0)
return (error);
return (dovchflags(p, nd.ni_vp, flags));
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p);
nd.ni_pledge = PLEDGE_FATTR | PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_WRITE;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p);
nd.ni_pledge = PLEDGE_CHOWN | PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_WRITE;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
nd.ni_pledge = PLEDGE_CHOWN | PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_WRITE;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
NDINITAT(&nd, LOOKUP, follow, UIO_USERSPACE, fd, path, p);
nd.ni_pledge = PLEDGE_FATTR | PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_WRITE;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
nd.ni_pledge = PLEDGE_FATTR | PLEDGE_RPATH;
+ nd.ni_unveil = UNVEIL_WRITE;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
NDINITAT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
fromfd, from, p);
fromnd.ni_pledge = PLEDGE_RPATH | PLEDGE_CPATH;
+ fromnd.ni_unveil = UNVEIL_READ | UNVEIL_CREATE;
if ((error = namei(&fromnd)) != 0)
return (error);
fvp = fromnd.ni_vp;
NDINITAT(&tond, RENAME, flags, UIO_USERSPACE, tofd, to, p);
tond.ni_pledge = PLEDGE_CPATH;
+ tond.ni_unveil = UNVEIL_CREATE;
if ((error = namei(&tond)) != 0) {
VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
vrele(fromnd.ni_dvp);
NDINITAT(&nd, CREATE, LOCKPARENT | STRIPSLASHES, UIO_USERSPACE,
fd, path, p);
nd.ni_pledge = PLEDGE_CPATH;
+ nd.ni_unveil = UNVEIL_CREATE;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
nd.ni_pledge = PLEDGE_RPATH | PLEDGE_TTY;
+ nd.ni_unveil = UNVEIL_READ;
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;