~indicator-applet-developers/ubuntu-app-launch/trunk.17.04

168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
1
/*
2
 * Copyright © 2014 Canonical Ltd.
3
 *
4
 * This program is free software: you can redistribute it and/or modify it
5
 * under the terms of the GNU General Public License version 3, as published
6
 * by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but
9
 * WITHOUT ANY WARRANTY; without even the implied warranties of
10
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11
 * PURPOSE.  See the GNU General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU General Public License along
14
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 *
16
 * Authors:
17
 *     Ted Gould <ted.gould@canonical.com>
18
 */
19
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
20
#define _POSIX_C_SOURCE 200809L
21
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
22
#include <stdlib.h>
23
#include <stdio.h>
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
24
#include <unistd.h>
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
25
#include <errno.h>
26
#include <string.h>
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
27
#include <fcntl.h>
28
#include <sys/stat.h>
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
29
30
int
31
main (int argc, char * argv[])
32
{
33
	if (argc != 3) {
168.3.6 by Ted Gould
No fancy printing libraries here
34
		fprintf(stderr, "Usage: %s <pid> <value>\n", argv[0]);
168.3.10 by Ted Gould
Use symbolic names for exit values
35
		exit(EXIT_FAILURE);
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
36
	}
37
168.3.16 by Ted Gould
Parse and verify the OOM value as well
38
	/* Not we turn the pid into an integer and back so that we can ensure we don't
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
39
	   get used for nefarious tasks. */
40
	int pidval = atoi(argv[1]);
41
	if ((pidval < 1) || (pidval >= 32768)) {
168.3.11 by Ted Gould
Remove argument strings from error messages
42
		fprintf(stderr, "PID passed is invalid: %d\n", pidval);
168.3.10 by Ted Gould
Use symbolic names for exit values
43
		exit(EXIT_FAILURE);
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
44
	}
45
168.3.16 by Ted Gould
Parse and verify the OOM value as well
46
	/* Not we turn the oom value into an integer and back so that we can ensure we don't
47
	   get used for nefarious tasks. */
48
	int oomval = atoi(argv[2]);
49
	if ((oomval < -1000) || (oomval >= 1000)) {
50
		fprintf(stderr, "OOM Value passed is invalid: %d\n", oomval);
51
		exit(EXIT_FAILURE);
52
	}
53
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
54
	/* Open up the PID directory first, to ensure that it is actually one of
55
	   ours, so that we can't be used to set a OOM value on just anything */
56
	char pidpath[32];
57
	snprintf(pidpath, sizeof(pidpath), "/proc/%d", pidval);
58
59
	int piddir = open(pidpath, O_RDONLY | O_DIRECTORY);
60
	if (piddir < 0) {
168.3.11 by Ted Gould
Remove argument strings from error messages
61
		fprintf(stderr, "Unable open PID directory '%s' for '%d': %s\n", pidpath, pidval, strerror(errno));
168.3.10 by Ted Gould
Use symbolic names for exit values
62
		exit(EXIT_FAILURE);
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
63
	}
64
65
	struct stat piddirstat = {0};
168.3.7 by Ted Gould
Bad check
66
	if (fstat(piddir, &piddirstat) < 0) {
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
67
		close(piddir);
168.3.11 by Ted Gould
Remove argument strings from error messages
68
		fprintf(stderr, "Unable stat PID directory '%s' for '%d': %s\n", pidpath, pidval, strerror(errno));
168.3.10 by Ted Gould
Use symbolic names for exit values
69
		exit(EXIT_FAILURE);
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
70
	}
71
72
	if (getuid() != piddirstat.st_uid) {
73
		close(piddir);
168.3.6 by Ted Gould
No fancy printing libraries here
74
		fprintf(stderr, "PID directory '%s' is not owned by %d but by %d\n", pidpath, getuid(), piddirstat.st_uid);
168.3.10 by Ted Gould
Use symbolic names for exit values
75
		exit(EXIT_FAILURE);
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
76
	}
77
78
	/* Looks good, let's try to get the actual oom_adj_score file to write
79
	   the value to it. */
80
	int adj = openat(piddir, "oom_score_adj", O_WRONLY);
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
81
	int openerr = errno;
82
168.3.12 by Ted Gould
Check less that zero for open
83
	if (adj < 0) {
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
84
		close(piddir);
85
168.3.15 by Ted Gould
Fix return to be an exit
86
		/* ENOENT happens a fair amount because of races, so it's not
87
		   worth printing a warning about */
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
88
		if (openerr != ENOENT) {
168.3.16 by Ted Gould
Parse and verify the OOM value as well
89
			fprintf(stderr, "Unable to set OOM value of '%d' on '%d': %s\n", oomval, pidval, strerror(openerr));
168.3.15 by Ted Gould
Fix return to be an exit
90
			exit(EXIT_FAILURE);
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
91
		} else {
168.3.10 by Ted Gould
Use symbolic names for exit values
92
			exit(EXIT_SUCCESS);
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
93
		}
94
	}
95
168.3.16 by Ted Gould
Parse and verify the OOM value as well
96
	char oomstring[32];
97
	snprintf(oomstring, sizeof(oomstring), "%d", oomval);
98
99
	size_t writesize = write(adj, oomstring, strlen(oomstring));
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
100
	int writeerr = errno;
168.3.5 by Ted Gould
Reset so that we're checking the directory first, use that directory that we have open.
101
102
	close(adj);
103
	close(piddir);
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
104
168.3.16 by Ted Gould
Parse and verify the OOM value as well
105
	if (writesize == strlen(oomstring))
168.3.10 by Ted Gould
Use symbolic names for exit values
106
		exit(EXIT_SUCCESS);
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
107
	
108
	if (writeerr != 0)
168.3.16 by Ted Gould
Parse and verify the OOM value as well
109
		fprintf(stderr, "Unable to set OOM value of '%d' on '%d': %s\n", oomval, pidval, strerror(writeerr));
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
110
	else
111
		/* No error, but yet, wrong size. Not sure, what could cause this. */
168.3.16 by Ted Gould
Parse and verify the OOM value as well
112
		fprintf(stderr, "Unable to set OOM value of '%d' on '%d': Wrote %d bytes\n", oomval, pidval, (int)writesize);
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
113
168.3.10 by Ted Gould
Use symbolic names for exit values
114
	exit(EXIT_FAILURE);
168.3.2 by Ted Gould
Starting out a little helper to make setuid and help us if we don't have permissions <cough>oxide</cough>
115
}