On Mon, Jul 30, 2018 at 07:55:35AM -0600, Bob Beck wrote:
> yeah the latter will be the way to go
> 

new diff with direct lookup using an indirection table.

first reorders PLEDGE flags to have:
  - PLEDGE promises that could occurs in ni_pledge and are used for
    unveil(2)

  - PLEDGE promises that could occurs in ni_pledge and aren't used for
    unveil(2) (as PLEDGE_UNVEIL, PLEDGE_STAT, PLEDGE_STATLIE)

  - others promises

  - so I redefined PLEDGE_USERSET a bit differently (as some of these
    flags are used in ni_pledge)

there is 8 different promises for the first category. So we just need a
256 long array to have a table to direct lookup PLEDGE -> UNVEIL.

for representing UNVEIL flags, I changed type from uint64_t to u_char.

I hooked a init function in taskq_init() in order to properly initialize
the lookup array, but I am unsure of the placement.

some names for constants/variable could have better names, but I had no
inspiration.

Thanks.
-- 
Sebastien Marie

Index: sys/pledge.h
===================================================================
RCS file: /cvs/src/sys/sys/pledge.h,v
retrieving revision 1.37
diff -u -p -r1.37 pledge.h
--- sys/pledge.h        13 Jul 2018 09:25:23 -0000      1.37
+++ sys/pledge.h        2 Aug 2018 12:51:28 -0000
@@ -23,54 +23,64 @@
 #include <sys/cdefs.h>
 
 /*
- * pledge(2) requests
+ * pledge(2) promises
  */
 #define PLEDGE_ALWAYS  0xffffffffffffffffULL
+
+/* promises used in ni_pledge */
 #define PLEDGE_RPATH   0x0000000000000001ULL   /* allow open for read */
 #define PLEDGE_WPATH   0x0000000000000002ULL   /* allow open for write */
 #define PLEDGE_CPATH   0x0000000000000004ULL   /* allow creat, mkdir, unlink 
etc */
-#define PLEDGE_STDIO   0x0000000000000008ULL   /* operate on own pid */
-#define PLEDGE_TMPPATH 0x0000000000000010ULL   /* for mk*temp() */
-#define PLEDGE_DNS     0x0000000000000020ULL   /* DNS services */
-#define PLEDGE_INET    0x0000000000000040ULL   /* AF_INET/AF_INET6 sockets */
-#define PLEDGE_FLOCK   0x0000000000000080ULL   /* file locking */
-#define PLEDGE_UNIX    0x0000000000000100ULL   /* AF_UNIX sockets */
-#define PLEDGE_ID      0x0000000000000200ULL   /* allow setuid, setgid, etc */
-#define PLEDGE_TAPE    0x0000000000000400ULL   /* Tape ioctl */
-#define PLEDGE_GETPW   0x0000000000000800ULL   /* YP enables if ypbind.lock */
-#define PLEDGE_PROC    0x0000000000001000ULL   /* fork, waitpid, etc */
-#define PLEDGE_SETTIME 0x0000000000002000ULL   /* able to set/adj time/freq */
-#define PLEDGE_FATTR   0x0000000000004000ULL   /* allow explicit file st_* 
mods */
-#define PLEDGE_PROTEXEC        0x0000000000008000ULL   /* allow use of 
PROT_EXEC */
-#define PLEDGE_TTY     0x0000000000010000ULL   /* tty setting */
-#define PLEDGE_SENDFD  0x0000000000020000ULL   /* AF_UNIX CMSG fd sending */
-#define PLEDGE_RECVFD  0x0000000000040000ULL   /* AF_UNIX CMSG fd receiving */
-#define PLEDGE_EXEC    0x0000000000080000ULL   /* execve, child is free of 
pledge */
-#define PLEDGE_ROUTE   0x0000000000100000ULL   /* routing lookups */
-#define PLEDGE_MCAST   0x0000000000200000ULL   /* multicast joins */
-#define PLEDGE_VMINFO  0x0000000000400000ULL   /* vminfo listings */
-#define PLEDGE_PS      0x0000000000800000ULL   /* ps listings */
-#define PLEDGE_DISKLABEL 0x0000000002000000ULL /* disklabels */
-#define PLEDGE_PF      0x0000000004000000ULL   /* pf ioctls */
-#define PLEDGE_AUDIO   0x0000000008000000ULL   /* audio ioctls */
-#define PLEDGE_DPATH   0x0000000010000000ULL   /* mknod & mkfifo */
-#define PLEDGE_DRM     0x0000000020000000ULL   /* drm ioctls */
-#define PLEDGE_VMM     0x0000000040000000ULL   /* vmm ioctls */
-#define PLEDGE_CHOWN   0x0000000080000000ULL   /* chown(2) family */
-#define PLEDGE_CHOWNUID        0x0000000100000000ULL   /* allow owner/group 
changes */
-#define PLEDGE_BPF     0x0000000200000000ULL   /* bpf ioctl */
-#define PLEDGE_ERROR   0x0000000400000000ULL   /* ENOSYS instead of kill */
-#define PLEDGE_WROUTE  0x0000000800000000ULL   /* interface address ioctls */
-#define PLEDGE_UNVEIL  0x0000001000000000ULL   /* allow unveil() */
+#define PLEDGE_DPATH   0x0000000000000008ULL   /* mknod & mkfifo */
+#define PLEDGE_FATTR   0x0000000000000010ULL   /* allow explicit file st_* 
mods */
+#define PLEDGE_TTY     0x0000000000000020ULL   /* tty setting */
+#define PLEDGE_UNIX    0x0000000000000040ULL   /* AF_UNIX sockets */
+#define PLEDGE_EXEC    0x0000000000000080ULL   /* execve, child is free of 
pledge */
+
+#define UNVEIL_PLDGMASK        0x00000000000000ffULL
+
+/* these could occurs in ni_pledge but are ignored */
+#define PLEDGE_UNVEIL  0x0000000000000100ULL   /* allow unveil() */
+#define PLEDGE_STAT    0x0000000000000200ULL   /* XXX this is a stat */
+#define PLEDGE_STATLIE 0x0000000000000400ULL
+
+#define UNVEIL_PLDGIGN 0x0000000000000700ULL
+
+/* others promises */
+#define PLEDGE_STDIO   0x0000000000000800ULL   /* operate on own pid */
+#define PLEDGE_TMPPATH 0x0000000000001000ULL   /* for mk*temp() */
+#define PLEDGE_DNS     0x0000000000002000ULL   /* DNS services */
+#define PLEDGE_INET    0x0000000000004000ULL   /* AF_INET/AF_INET6 sockets */
+#define PLEDGE_FLOCK   0x0000000000008000ULL   /* file locking */
+#define PLEDGE_ID      0x0000000000010000ULL   /* allow setuid, setgid, etc */
+#define PLEDGE_TAPE    0x0000000000020000ULL   /* Tape ioctl */
+#define PLEDGE_GETPW   0x0000000000040000ULL   /* YP enables if ypbind.lock */
+#define PLEDGE_PROC    0x0000000000080000ULL   /* fork, waitpid, etc */
+#define PLEDGE_SETTIME 0x0000000000100000ULL   /* able to set/adj time/freq */
+#define PLEDGE_PROTEXEC        0x0000000000200000ULL   /* allow use of 
PROT_EXEC */
+#define PLEDGE_SENDFD  0x0000000000400000ULL   /* AF_UNIX CMSG fd sending */
+#define PLEDGE_RECVFD  0x0000000000800000ULL   /* AF_UNIX CMSG fd receiving */
+#define PLEDGE_ROUTE   0x0000000001000000ULL   /* routing lookups */
+#define PLEDGE_MCAST   0x0000000002000000ULL   /* multicast joins */
+#define PLEDGE_VMINFO  0x0000000004000000ULL   /* vminfo listings */
+#define PLEDGE_PS      0x0000000008000000ULL   /* ps listings */
+#define PLEDGE_DISKLABEL 0x0000000010000000ULL /* disklabels */
+#define PLEDGE_PF      0x0000000020000000ULL   /* pf ioctls */
+#define PLEDGE_AUDIO   0x0000000040000000ULL   /* audio ioctls */
+#define PLEDGE_DRM     0x0000000080000000ULL   /* drm ioctls */
+#define PLEDGE_VMM     0x0000000100000000ULL   /* vmm ioctls */
+#define PLEDGE_CHOWN   0x0000000200000000ULL   /* chown(2) family */
+#define PLEDGE_CHOWNUID        0x0000000400000000ULL   /* allow owner/group 
changes */
+#define PLEDGE_BPF     0x0000000800000000ULL   /* bpf ioctl */
+#define PLEDGE_ERROR   0x0000001000000000ULL   /* ENOSYS instead of kill */
+#define PLEDGE_WROUTE  0x0000002000000000ULL   /* interface address ioctls */
+#define PLEDGE_YPACTIVE        0x0000004000000000ULL   /* YP use detected and 
allowed */
 
 /*
  * Bits outside PLEDGE_USERSET are used by the kernel itself
  * to track program behaviours which have been observed.
  */
-#define PLEDGE_USERSET 0x0fffffffffffffffULL
-#define PLEDGE_STAT    0x2000000000000000ULL   /* XXX this is a stat */
-#define PLEDGE_STATLIE 0x4000000000000000ULL
-#define PLEDGE_YPACTIVE        0x8000000000000000ULL   /* YP use detected and 
allowed */
+#define        PLEDGE_USERSET  (~(PLEDGE_STAT|PLEDGE_STATLIE|PLEDGE_YPACTIVE))
 
 #ifdef PLEDGENAMES
 static struct {
Index: sys/proc.h
===================================================================
RCS file: /cvs/src/sys/sys/proc.h,v
retrieving revision 1.254
diff -u -p -r1.254 proc.h
--- sys/proc.h  28 Jul 2018 18:07:26 -0000      1.254
+++ sys/proc.h  2 Aug 2018 12:01:30 -0000
@@ -130,7 +130,7 @@ struct tusage {
 struct unvname {
        char                    *un_name;
        size_t                  un_namesize;
-       uint64_t                un_flags;
+       u_char                  un_flags;
        RBT_ENTRY(unvnmae)      un_rbt;
 };
 
@@ -424,7 +424,7 @@ struct unveil {
        struct vnode            *uv_vp;
        struct unvname_rbt      uv_names;
        struct rwlock           uv_lock;
-       u_int64_t               uv_flags;
+       u_char                  uv_flags;
 };
 
 struct uidinfo {
Index: kern/kern_unveil.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_unveil.c,v
retrieving revision 1.9
diff -u -p -r1.9 kern_unveil.c
--- kern/kern_unveil.c  30 Jul 2018 15:16:27 -0000      1.9
+++ kern/kern_unveil.c  2 Aug 2018 13:13:43 -0000
@@ -40,6 +40,51 @@
 #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 u_char uv_nipledget[UNVEIL_PLDGMASK+1];
+
+void
+unveil_init_nipledget()
+{
+       size_t i, j;
+       static const struct {
+               uint64_t pledge;
+               u_char   unveil;
+       } conv[] = {
+               { PLEDGE_RPATH, UNVEIL_READ },
+               { PLEDGE_WPATH, UNVEIL_WRITE },
+               { PLEDGE_CPATH, UNVEIL_CREATE },
+               { PLEDGE_DPATH, UNVEIL_CREATE },
+               { PLEDGE_FATTR, UNVEIL_WRITE },
+               { PLEDGE_TTY, UNVEIL_READ | UNVEIL_WRITE },
+               { PLEDGE_UNIX, UNVEIL_READ | UNVEIL_WRITE },
+               { PLEDGE_EXEC, UNVEIL_EXEC },
+       };
+
+       for (i=0; i < nitems(uv_nipledget); i++)
+               for (j=0; j < nitems(conv); j++)
+                       if (ISSET(i, conv[j].pledge))
+                               SET(uv_nipledget[i], conv[j].unveil);
+}
+
+static inline u_char
+unveil_nipledge_lookup(uint64_t pledge)
+{
+       /* ignore these bits */
+       pledge &= ~UNVEIL_PLDGIGN;
+
+       /* do not overflow */
+       if ((pledge & ~UNVEIL_PLDGMASK) != 0)
+               panic("unveil_nipledge_lookup: unexpected pledge bits: %llu\n",
+                   pledge & ~UNVEIL_PLDGMASK);
+
+       return uv_nipledget[pledge];
+}
+
 static inline int
 unvname_compare(const struct unvname *n1, const struct unvname *n2)
 {
@@ -50,7 +95,7 @@ unvname_compare(const struct unvname *n1
 }
 
 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);
@@ -118,7 +163,7 @@ unveil_delete_names(struct unveil *uv)
 }
 
 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;
 
@@ -310,7 +355,7 @@ unveil_lookup(struct vnode *vp, struct p
 }
 
 int
-unveil_parsepermissions(const char *permissions, uint64_t *perms)
+unveil_parsepermissions(const char *permissions, u_char *perms)
 {
        size_t i = 0;
        char c;
@@ -319,16 +364,16 @@ unveil_parsepermissions(const char *perm
        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;
@@ -338,7 +383,7 @@ unveil_parsepermissions(const char *perm
 }
 
 int
-unveil_setflags(uint64_t *flags, uint64_t nflags)
+unveil_setflags(u_char *flags, u_char nflags)
 {
 #if 0
        if (((~(*flags)) & nflags) != 0) {
@@ -403,7 +448,7 @@ unveil_add(struct proc *p, struct nameid
        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 */
 
@@ -530,8 +575,10 @@ unveil_add(struct proc *p, struct nameid
  * 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)
 {
+       u_char ni_unveil;
+
        if (flags == 0) {
                if (ni->ni_pledge & PLEDGE_STAT) {
 #ifdef DEBUG_UNVEIL
@@ -552,32 +599,35 @@ unveil_flagmatch(struct nameidata *ni, u
                CLR(ni->ni_pledge, PLEDGE_STATLIE);
                return 1;
        }
-       if (ni->ni_pledge & PLEDGE_RPATH) {
-               if ((flags & PLEDGE_RPATH) == 0) {
+
+       ni_unveil = unveil_nipledge_lookup(ni->ni_pledge);
+
+       if (ni_unveil & UNVEIL_READ) {
+               if ((flags & UNVEIL_READ) == 0) {
 #ifdef DEBUG_UNVEIL
                        printf("Pledge wants read but disallowed\n");
 #endif
                        return 0;
                }
        }
-       if (ni->ni_pledge & PLEDGE_WPATH) {
-               if ((flags & PLEDGE_WPATH) == 0) {
+       if (ni_unveil & UNVEIL_WRITE) {
+               if ((flags & UNVEIL_WRITE) == 0) {
 #ifdef DEBUG_UNVEIL
                        printf("Pledge wants write but disallowed\n");
 #endif
                        return 0;
                }
        }
-       if (ni->ni_pledge & PLEDGE_EXEC) {
-               if ((flags & PLEDGE_EXEC) == 0) {
+       if (ni_unveil & UNVEIL_EXEC) {
+               if ((flags & UNVEIL_EXEC) == 0) {
 #ifdef DEBUG_UNVEIL
                        printf("Pledge wants exec but disallowed\n");
 #endif
                        return 0;
                }
        }
-       if (ni->ni_pledge & PLEDGE_CPATH) {
-               if ((flags & PLEDGE_CPATH) == 0) {
+       if (ni_unveil & UNVEIL_CREATE) {
+               if ((flags & UNVEIL_CREATE) == 0) {
 #ifdef DEBUG_UNVEIL
                        printf("Pledge wants cpath but disallowed\n");
 #endif
Index: kern/init_main.c
===================================================================
RCS file: /cvs/src/sys/kern/init_main.c,v
retrieving revision 1.279
diff -u -p -r1.279 init_main.c
--- kern/init_main.c    20 Jul 2018 21:57:26 -0000      1.279
+++ kern/init_main.c    2 Aug 2018 12:26:21 -0000
@@ -150,6 +150,7 @@ void        taskq_init(void);
 void   timeout_proc_init(void);
 void   pool_gc_pages(void *);
 void   percpu_init(void);
+void   unveil_init_nipledget(void);
 
 extern char sigcode[], esigcode[], sigcoderet[];
 #ifdef SYSCALL_DEBUG
@@ -374,6 +375,7 @@ main(void *framep)
        percpu_init();
 
        /* Initialize the file systems. */
+       unveil_init_nipledget();
 #if defined(NFSSERVER) || defined(NFSCLIENT)
        nfs_init();                     /* initialize server/shared data */
 #endif

Reply via email to