pledge(2): stdio: permit restricted profil(2) for moncontrol(3)
authorcheloha <cheloha@openbsd.org>
Fri, 2 Jun 2023 17:44:29 +0000 (17:44 +0000)
committercheloha <cheloha@openbsd.org>
Fri, 2 Jun 2023 17:44:29 +0000 (17:44 +0000)
Currently, pledged '-pg' binaries get killed in _mcleanup() when they
try to disable profil(2) via moncontrol(3).

Disabling profil(2) is harmless.  Add profil(2) to the "stdio"
pledge(2) promise and permit profil(2) calls when the scale argument
is zero.  Enabling profil(2) remains forbidden in pledged processes.

This gets us one step closer to making '-pg' binaries compatible with
pledge(2).  The next step is to decide how to exfiltrate the profiling
data from the process during _mcleanup().

Prompted by semarie@.  Cleaned up by deraadt@.  With input from
deraadt@, espie@, and semarie@.

"Looks good" deraadt@
pledge(2) pieces ok semarie@

lib/libc/sys/pledge.2
sys/kern/kern_pledge.c
sys/kern/subr_prof.c
sys/sys/pledge.h

index 678396c..5cca1fb 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pledge.2,v 1.65 2023/05/19 01:12:23 guenther Exp $
+.\" $OpenBSD: pledge.2,v 1.66 2023/06/02 17:44:29 cheloha Exp $
 .\"
 .\" Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: May 19 2023 $
+.Dd $Mdocdate: June 2 2023 $
 .Dt PLEDGE 2
 .Os
 .Sh NAME
@@ -134,6 +134,8 @@ May open
 .Pa /etc/localtime
 and any files below
 .Pa /usr/share/zoneinfo .
+.It Xr profil 2 :
+Can only disable profiling.
 .It Fn pledge :
 Can only reduce permissions for
 .Fa promises
@@ -209,6 +211,7 @@ As a result, all the expected functionalities of libc stdio work.
 .Xr poll 2 ,
 .Xr pread 2 ,
 .Xr preadv 2 ,
+.Xr profil 2 ,
 .Xr pwrite 2 ,
 .Xr pwritev 2 ,
 .Xr read 2 ,
index 15a0ae3..de98202 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_pledge.c,v 1.305 2023/05/19 01:12:23 guenther Exp $      */
+/*     $OpenBSD: kern_pledge.c,v 1.306 2023/06/02 17:44:29 cheloha Exp $       */
 
 /*
  * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
@@ -145,6 +145,9 @@ const uint64_t pledge_syscalls[SYS_MAXSYSCALL] = {
         */
        [SYS_sysctl] = PLEDGE_STDIO,
 
+       /* For moncontrol(3).  Only allowed to disable profiling. */
+       [SYS_profil] = PLEDGE_STDIO,
+
        /* Support for malloc(3) family of operations */
        [SYS_getentropy] = PLEDGE_STDIO,
        [SYS_madvise] = PLEDGE_STDIO,
@@ -1586,6 +1589,16 @@ pledge_kill(struct proc *p, pid_t pid)
        return pledge_fail(p, EPERM, PLEDGE_PROC);
 }
 
+int
+pledge_profil(struct proc *p, u_int scale)
+{
+       if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
+               return 0;
+       if (scale != 0)
+               return pledge_fail(p, EPERM, PLEDGE_STDIO);
+       return 0;
+}
+
 int
 pledge_protexec(struct proc *p, int prot)
 {
index 432c5e2..a93b6df 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: subr_prof.c,v 1.34 2023/05/30 08:30:01 jsg Exp $      */
+/*     $OpenBSD: subr_prof.c,v 1.35 2023/06/02 17:44:29 cheloha Exp $  */
 /*     $NetBSD: subr_prof.c,v 1.12 1996/04/22 01:38:50 christos Exp $  */
 
 /*-
@@ -34,6 +34,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/pledge.h>
 #include <sys/proc.h>
 #include <sys/resourcevar.h>
 #include <sys/mount.h>
@@ -236,7 +237,11 @@ sys_profil(struct proc *p, void *v, register_t *retval)
        } */ *uap = v;
        struct process *pr = p->p_p;
        struct uprof *upp;
-       int s;
+       int error, s;
+
+       error = pledge_profil(p, SCARG(uap, scale));
+       if (error)
+               return error;
 
        if (SCARG(uap, scale) > (1 << 16))
                return (EINVAL);
index 6098fb7..073ad9a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pledge.h,v 1.47 2022/09/01 05:40:46 jsg Exp $ */
+/*     $OpenBSD: pledge.h,v 1.48 2023/06/02 17:44:29 cheloha Exp $     */
 
 /*
  * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
@@ -138,6 +138,7 @@ int pledge_flock(struct proc *p);
 int    pledge_fcntl(struct proc *p, int cmd);
 int    pledge_swapctl(struct proc *p, int cmd);
 int    pledge_kill(struct proc *p, pid_t pid);
+int    pledge_profil(struct proc *, u_int);
 int    pledge_protexec(struct proc *p, int prot);
 
 #endif /* _KERNEL */