I believe it would be better to add setrtable to id pledge.

On 2022-01-29, Matthew Martin wrote:
> It would be nice to have the ability to set a user's rtable upon login.
> This would be useful both for road warrior VPN setups (put both the VPN
> interface and user in an rdomain other than 0) and to differentiate
> users in firewall rules on the gateway or unbound views on a resolver.
> The below patch adds an rtable capability to login.conf which sets the
> user's default rtable on login. 
> 
> Since setusercontext will now call setrtable, that syscall needs to be
> covered under some pledge promise. Since the wroute promise already
> allows programs to set a different rtable on a per socket basis, I don't
> think adding the setrtable syscall materially changes the scope or
> attack surface. This impacts dhcpleased, iked, rad, and slaacd which
> already use the wroute promise. The wroute promise is added to
> calendar, skeyaudit, su, cron, and inetd.
> 
> chroot, login, ssh, nsd, and unbound are impacted, but don't show up in
> the diff because they don't use pledge. ssh continues to work as
> expected: the user's session has the login specified default rtable;
> however, the socket connecting the user to the session remains in the
> original rtable so the connection doesn't break. nsd and unbound open
> their listening sockets prior to privdrop, so those sockets are in the
> original rtable (which should be set via rcctl). Notifications and XFRs
> for nsd and lookups for unbound happen in the login specified rtable.
> While this is somewhat surprising, I think most people would set the
> rtable for a daemon via rcctl.
> 
> doas is a bit of a special case: it explicitly lists the LOGIN_ flags
> rather than using LOGIN_SETALL and removing specific flags. I am
> inclined to say doas should also set the default rtable, but it's not
> a strong stance. I've left it out of this version of the patch pending
> feedback on how others feel.
> 
> In addition xenodm would need to add wroute to the pledge in dm.c
> StartDisplay and to the first pledge in session.c StartClient.
> 
> From a Debian code search the ports which use LOGIN_SETALL appear to be
> mail/alpine, security/sudo, and x11/gnome/gdm. None of these ports have
> pledge markers in their Makefile.
> 
> Finally it may be nicer to drop -a from calendar and skeyaudit. Each
> user that desires the service could then create their own cron job.
> While it would allow a fair bit of code to be deleted and a tighter
> pledge, it would break existing workflows and could be considered as
> in a separate thread if desired.
> 
> - Matthew Martin
> 
> 
> 
> diff --git include/login_cap.h include/login_cap.h
> index d9a4c2c349c..1e831b6471a 100644
> --- include/login_cap.h
> +++ include/login_cap.h
> @@ -53,7 +53,8 @@
>  #define      LOGIN_SETUMASK          0x0020  /* Set umask */
>  #define      LOGIN_SETUSER           0x0040  /* Set user */
>  #define      LOGIN_SETENV            0x0080  /* Set environment */
> -#define      LOGIN_SETALL            0x00ff  /* Set all. */
> +#define      LOGIN_SETRTABLE         0x0100  /* Set rtable */
> +#define      LOGIN_SETALL            0x01ff  /* Set all. */
>  
>  #define      BI_AUTH         "authorize"             /* Accepted 
> authentication */
>  #define      BI_REJECT       "reject"                /* Rejected 
> authentication */
> diff --git lib/libc/gen/login_cap.c lib/libc/gen/login_cap.c
> index 862f33b2065..65848f09ef6 100644
> --- lib/libc/gen/login_cap.c
> +++ lib/libc/gen/login_cap.c
> @@ -52,6 +52,7 @@
>  #include <sys/stat.h>
>  #include <sys/time.h>
>  #include <sys/resource.h>
> +#include <sys/socket.h>
>  
>  #include <err.h>
>  #include <errno.h>
> @@ -574,7 +575,7 @@ int
>  setusercontext(login_cap_t *lc, struct passwd *pwd, uid_t uid, u_int flags)
>  {
>       login_cap_t *flc;
> -     quad_t p;
> +     quad_t p, rtable;
>       int i;
>  
>       flc = NULL;
> @@ -625,6 +626,14 @@ setusercontext(login_cap_t *lc, struct passwd *pwd, 
> uid_t uid, u_int flags)
>               umask((mode_t)p);
>       }
>  
> +     if (flags & LOGIN_SETRTABLE) {
> +             rtable = login_getcapnum(lc, "rtable", 0, 0);
> +
> +             if (setrtable((int)rtable) == -1) {
> +                     syslog(LOG_ERR, "%s: setrtable: %m", lc->lc_class);
> +             }
> +     }
> +
>       if (flags & LOGIN_SETGROUP) {
>               if (setresgid(pwd->pw_gid, pwd->pw_gid, pwd->pw_gid) == -1) {
>                       syslog(LOG_ERR, "setresgid(%u,%u,%u): %m",
> diff --git share/man/man5/login.conf.5 share/man/man5/login.conf.5
> index da935fa223e..ffeafc3531c 100644
> --- share/man/man5/login.conf.5
> +++ share/man/man5/login.conf.5
> @@ -276,6 +276,10 @@ Initial priority (nice) level.
>  Require home directory to login.
>  .\"
>  .Pp
> +.It rtable Ta number Ta Dv 0 Ta
> +Rtable to be set for the class.
> +.\"
> +.Pp
>  .It setenv Ta envlist Ta "" Ta
>  A list of environment variables and associated values to be set for the 
> class.
>  .\"
> diff --git sys/kern/kern_pledge.c sys/kern/kern_pledge.c
> index 6687bf91f09..901d41cefb6 100644
> --- sys/kern/kern_pledge.c
> +++ sys/kern/kern_pledge.c
> @@ -373,6 +373,8 @@ const uint64_t pledge_syscalls[SYS_MAXSYSCALL] = {
>       [SYS_flock] = PLEDGE_FLOCK | PLEDGE_YPACTIVE,
>  
>       [SYS_swapctl] = PLEDGE_VMINFO,  /* XXX should limit to "get" operations 
> */
> +
> +     [SYS_setrtable] = PLEDGE_WROUTE,
>  };
>  
>  static const struct {
> diff --git usr.bin/calendar/calendar.c usr.bin/calendar/calendar.c
> index ad82a94707c..bda19f4c6a6 100644
> --- usr.bin/calendar/calendar.c
> +++ usr.bin/calendar/calendar.c
> @@ -126,7 +126,7 @@ main(int argc, char *argv[])
>               usage();
>  
>       if (doall) {
> -             if (pledge("stdio rpath tmppath fattr getpw id proc exec", NULL)
> +             if (pledge("stdio rpath tmppath fattr getpw id proc exec 
> wroute", NULL)
>                   == -1)
>                       err(1, "pledge");
>       } else {
> diff --git usr.bin/skeyaudit/skeyaudit.c usr.bin/skeyaudit/skeyaudit.c
> index 3cad9b2eafa..1462d677650 100644
> --- usr.bin/skeyaudit/skeyaudit.c
> +++ usr.bin/skeyaudit/skeyaudit.c
> @@ -71,7 +71,7 @@ main(int argc, char **argv)
>       char *name;
>       int ch, left, aflag, iflag, limit;
>  
> -     if (pledge("stdio rpath wpath flock getpw proc exec id", NULL) == -1)
> +     if (pledge("stdio rpath wpath flock getpw proc exec id wroute", NULL) 
> == -1)
>               err(1, "pledge");
>  
>       aflag = iflag = 0;
> diff --git usr.bin/su/su.c usr.bin/su/su.c
> index f9fb2c0ac88..1fc73fa36bd 100644
> --- usr.bin/su/su.c
> +++ usr.bin/su/su.c
> @@ -73,7 +73,7 @@ main(int argc, char **argv)
>       uid_t ruid;
>       u_int flags;
>  
> -     if (pledge("stdio unveil rpath getpw proc exec id", NULL) == -1)
> +     if (pledge("stdio unveil rpath getpw proc exec id wroute", NULL) == -1)
>               err(1, "pledge");
>  
>       while ((ch = getopt(argc, argv, "a:c:fKLlms:-")) != -1)
> @@ -232,7 +232,7 @@ main(int argc, char **argv)
>       if (pwd == NULL)
>               auth_errx(as, 1, "internal error");
>  
> -     if (pledge("stdio unveil rpath getpw exec id", NULL) == -1)
> +     if (pledge("stdio unveil rpath getpw exec id wroute", NULL) == -1)
>               err(1, "pledge");
>  
>       if (!altshell) {
> @@ -309,7 +309,7 @@ main(int argc, char **argv)
>               if (setenv("SHELL", shell, 1) == -1)
>                       auth_err(as, 1, "unable to set environment");
>       }
> -     if (pledge("stdio rpath getpw exec id", NULL) == -1)
> +     if (pledge("stdio rpath getpw exec id wroute", NULL) == -1)
>               err(1, "pledge");
>  
>       np = *argv ? argv : argv - 1;
> diff --git usr.sbin/cron/cron.c usr.sbin/cron/cron.c
> index 831a70d5411..033864b1369 100644
> --- usr.sbin/cron/cron.c
> +++ usr.sbin/cron/cron.c
> @@ -99,7 +99,7 @@ main(int argc, char *argv[])
>  
>       openlog(__progname, LOG_PID, LOG_CRON);
>  
> -     if (pledge("stdio rpath wpath cpath fattr getpw unix id dns proc exec",
> +     if (pledge("stdio rpath wpath cpath fattr getpw unix id dns proc exec 
> wroute",
>           NULL) == -1) {
>               warn("pledge");
>               syslog(LOG_ERR, "(CRON) PLEDGE (%m)");
> diff --git usr.sbin/inetd/inetd.c usr.sbin/inetd/inetd.c
> index 2c623ef66d1..6ad2aec838b 100644
> --- usr.sbin/inetd/inetd.c
> +++ usr.sbin/inetd/inetd.c
> @@ -344,7 +344,7 @@ main(int argc, char *argv[])
>                       (void) setlogin("");
>       }
>  
> -     if (pledge("stdio rpath cpath getpw dns inet unix proc exec id", NULL) 
> == -1)
> +     if (pledge("stdio rpath cpath getpw dns inet unix proc exec id wroute", 
> NULL) == -1)
>               err(1, "pledge");
>  
>       if (uid == 0) {
> 
> 

Reply via email to