I wanted to get the memory map of a child proc with sysctl but noticed
I could only do this as root. I am allowed to ptrace it though so it
felt a bit unfair..
..so what about doing some of the the same checks as is done upon
PT_ATTACH? (and hijacking the global_ptrace global to mean we can get
the memory map also from not direct descending processes if we want).
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.305
diff -u -p -u -r1.305 kern_sysctl.c
--- sys/kern/kern_sysctl.c 27 May 2016 19:45:04 -0000 1.305
+++ sys/kern/kern_sysctl.c 27 Jun 2016 14:39:27 -0000
@@ -117,6 +117,7 @@ extern struct disklist_head disklist;
extern fixpt_t ccpu;
extern long numvnodes;
extern u_int net_livelocks;
+extern int global_ptrace;
extern void nmbclust_update(void);
@@ -1980,16 +1981,21 @@ sysctl_proc_vmmap(int *name, u_int namel
if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING))
return (EINVAL);
-#if 1
- /* XXX Allow only root for now */
- if ((error = suser(cp, 0)) != 0)
+ /* Only owner (unless the last exec gave it setuid/setgid
+ * privs) or root can get vmmap.
+ */
+ if ((findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid ||
+ ISSET(findpr->ps_flags, PS_SUGIDEXEC | PS_SUGID)) &&
+ (error = suser(cp, 0)) != 0) {
return (error);
-#else
- /* Only owner or root can get vmmap */
- if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid &&
- (error = suser(cp, 0)) != 0)
+ }
+
+ /* Must be a child (unless global_ptrace is set) */
+ if (global_ptrace == 0 && !inferior(findpr, cp->p_p) &&
+ (error = suser(cp, 0)) != 0) {
return (error);
-#endif
+ }
+
} else {
/* Only root can get kernel_map */
if ((error = suser(cp, 0)) != 0)
this makes the following snippet work:
#include <sys/param.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <err.h>
int main(int argc, char **argv)
{
int mib[3];
size_t len;
struct kinfo_vmentry entry;
len = sizeof(entry);
pid_t pid = fork();
if (pid == 0) {
sleep(6000);
exit(0);
}
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_VMMAP;
mib[2] = pid;
entry.kve_start = 0;
if (sysctl(mib, 3, &entry, &len, NULL, 0) == -1)
err(1, "sysctl");
printf("kve_start: 0x%lx, kve_end: 0x%lx\n", entry.kve_start, entry.kve_end);
entry.kve_start = entry.kve_start + 1;
u_long old_end = entry.kve_end;
while (sysctl(mib, 3, &entry, &len, NULL, 0) != -1) {
if (old_end == entry.kve_end)
break;
old_end = entry.kve_end;
printf("kve_start: 0x%lx, kve_end: 0x%lx\n", entry.kve_start,
entry.kve_end);
entry.kve_start = entry.kve_start + 1;
}
kill(pid, 9);
return 0;
}
output:
$ ./p_fork
kve_start: 0x1000, kve_end: 0x1000
kve_start: 0xf9e06100000, kve_end: 0xf9e06101000
kve_start: 0xf9e06200000, kve_end: 0xf9e06201000
kve_start: 0xf9e06301000, kve_end: 0xf9e06302000
kve_start: 0xf9e06401000, kve_end: 0xf9e06402000
kve_start: 0xf9e06501000, kve_end: 0xf9e06502000
kve_start: 0xfa0125d6000, kve_end: 0xfa0125d7000
kve_start: 0xfa016217000, kve_end: 0xfa016218000
[ .. ]
..and then one can do this in radare2 on OpenBSD:
$ r2 -d /bin/ls
Process with PID 18988 started...
attach 18988 18988
[0x12bd76c037f0]> dm
sys 0000 0x0000000000001000 - 0x0000000000001000 s ---- ?
sys 224K 0x000012bd76c00000 * 0x000012bd76c38000 s -r-x ?
sys 032K 0x000012bd76d38000 - 0x000012bd76d40000 s ---x ?
sys 0000 0x000012bd76e00000 - 0x000012bd76e00000 s ---- ?
sys 004K 0x000012bd76e40000 - 0x000012bd76e41000 s --wx ?
sys 004K 0x000012bd76f40000 - 0x000012bd76f41000 s --wx ?
sys 008K 0x000012bd77040000 - 0x000012bd77042000 s --wx ?
sys 004K 0x000012bd77042000 - 0x000012bd77043000 s --wx ?
sys 040K 0x000012bd77043000 - 0x000012bd7704d000 s --wx ?
sys 0000 0x000012bf76e00000 - 0x000012bf76e00000 s ---- ?
sys 004K 0x000012c036656000 - 0x000012c036657000 s -r-x ?
sys 028M 0x00007f7ffdff7000 - 0x00007f7fffbf7000 s ---- ?
sys 4.0M 0x00007f7fffbf7000 - 0x00007f7fffff0000 s --wx ?
sys 028K 0x00007f7fffff0000 - 0x00007f7fffff7000 s --wx ?
(the protection bits are flipped, ignore...)
Is there a better way?
/gabriel