Check-in [78a20d584e]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Customized secure-wrap for Fossil
Timelines: family | ancestors | descendants | both | setuid-fossil
Files: files | file ages | folders
SHA1: 78a20d584ee9fe5509ba394b60c3eb411be56ca2
User & Date: rkeene 2020-08-23 19:14:54
Context
2020-08-23
19:26
Finished reworking SUID changes check-in: b9a69f3282 user: rkeene tags: setuid-fossil
19:14
Customized secure-wrap for Fossil check-in: 78a20d584e user: rkeene tags: setuid-fossil
2020-08-20
17:36
Refactored SUID support check-in: c233a30944 user: rkeene tags: setuid-fossil
Changes

Changes to scripts/fossil-as-user/Makefile.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
all: suid-fossil secure-wrap

filter.h: generate-seccomp-filter filter.seccomp Makefile
	./generate-seccomp-filter filter.seccomp i386 "" x86_64 "" > filter.h.new
	mv filter.h.new filter.h

secure-wrap: secure-wrap.c filter.h
	gcc -o secure-wrap -W -Wall secure-wrap.c
	sudo chown root:root secure-wrap
	sudo chmod +s secure-wrap

clean:
	rm -f filter.h secure-wrap

distclean: clean

mrproper: distclean

.PHONY: all clean distclean
.SUFFIXES:






|
|












1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
all: suid-fossil secure-wrap

filter.h: generate-seccomp-filter filter.seccomp Makefile
	./generate-seccomp-filter filter.seccomp i386 "" x86_64 "" > filter.h.new
	mv filter.h.new filter.h

secure-wrap: secure-wrap.c filter.h Makefile
	gcc  -W -Wall -Wextra -Wno-type-limits -ansi -pedantic-errors -Werror -fPIC -DPIC -pie -fPIE -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -fno-strict-overflow -o secure-wrap secure-wrap.c
	sudo chown root:root secure-wrap
	sudo chmod +s secure-wrap

clean:
	rm -f filter.h secure-wrap

distclean: clean

mrproper: distclean

.PHONY: all clean distclean
.SUFFIXES:

Changes to scripts/fossil-as-user/filter.seccomp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19






20



21
22



23
24
25
26
27
28
29
..
40
41
42
43
44
45
46


47
48
49
50
51
52
53
..
66
67
68
69
70
71
72

73
74
75
76
77
78
79
..
85
86
87
88
89
90
91







92
93
94
95
96
97
i386 {
	return kill
}

x86_64 {
	if {$nr eq "socket"} {
		if {$args(0) != PF_LOCAL} {
			return errno EINVAL
		}
	}

	if {$nr in "setpgid"} {
		if {$args(0) == $args(1)} {
			return allow
		} else {
			return errno EACCES
		}
	}







	if {$nr in {



	    connect
	    select



	    readv
	    writev
	    madvise
	    tgkill
	    futex
	    access
	    arch_prctl
................................................................................
	    lseek
	    mmap
	    mprotect
	    munmap
	    open
	    fcntl
	    read


	    getdents
	    readlink
	    rt_sigaction
	    set_tid_address
	    uname
	    write
	    pipe
................................................................................
	    exit
	    mkdirat
	    mknodat
	    fchownat
	    futimesat
	    newfstatat
	    unlinkat

	    renameat
	    linkat
	    symlinkat
	    readlinkat
	    fchmodat
	    faccessat
	    set_robust_list
................................................................................
	    getegid
	    getppid
	    getpgrp
	    dup
	    dup2
	    dup3
	    rt_sigreturn







	}} {
		return allow
	}

	return errno ENOSYS
}






|












>
>
>
>
>
>

>
>
>


>
>
>







 







>
>







 







>







 







>
>
>
>
>
>
>






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
i386 {
	return kill
}

x86_64 {
	if {$nr eq "socket"} {
		if {$args(0) ni {PF_LOCAL PF_INET PF_INET6}} {
			return errno EINVAL
		}
	}

	if {$nr in "setpgid"} {
		if {$args(0) == $args(1)} {
			return allow
		} else {
			return errno EACCES
		}
	}

	if {$nr == "kill"} {
		if {$args(1) == 0} {
			return allow
		}
	}

	if {$nr in {
	    bind
	    socket
	    setsockopt
	    connect
	    select
	    poll
	    sendto
	    recvfrom
	    readv
	    writev
	    madvise
	    tgkill
	    futex
	    access
	    arch_prctl
................................................................................
	    lseek
	    mmap
	    mprotect
	    munmap
	    open
	    fcntl
	    read
	    pread64
	    pwrite64
	    getdents
	    readlink
	    rt_sigaction
	    set_tid_address
	    uname
	    write
	    pipe
................................................................................
	    exit
	    mkdirat
	    mknodat
	    fchownat
	    futimesat
	    newfstatat
	    unlinkat
	    unlink
	    renameat
	    linkat
	    symlinkat
	    readlinkat
	    fchmodat
	    faccessat
	    set_robust_list
................................................................................
	    getegid
	    getppid
	    getpgrp
	    dup
	    dup2
	    dup3
	    rt_sigreturn
	    prlimit64
	    setrlimit
	    getrusage
	    fsync
	    ftruncate
	    gettid
	    setsid
	}} {
		return allow
	}

	return errno ENOSYS
}

Changes to scripts/fossil-as-user/secure-wrap.c.

1
2
3
4


5
6
7
8
9
10
11
..
15
16
17
18
19
20
21


22
23
24
25
26
27
28
..
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
 * Simple wrapper that does chroot, seccomp,
 * and sets resource limits, before dropping privileges
 */



#include <linux/seccomp.h>
#include <linux/filter.h>
#include <sys/resource.h>
#include <linux/audit.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
................................................................................
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <errno.h>
#include <stdio.h>



#define SECURE_WRAP_MAX_ID 5242880LU
#define SECURE_WRAP_BASE_ID (1024LU * 1024LU)

#define check(command) if ((command) != 0) { perror(#command); return(1); }

#define error_eperm 1
................................................................................
	check(prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &filter));

	return(0);
}

int main(int argc, char **argv) {
	const char *directory, *program;
	char *program_environment[6];
	char *secure_home, *secure_user;
	char *id_string;
	unsigned long id;
	struct rlimit limit;
	unsigned int tmp_fd;

	program_environment[0] = "HOME=/";
	program_environment[1] = "TMPDIR=/tmp";
	program_environment[2] = "PATH=/bin";
	program_environment[3] = "TZ=UTC";
	program_environment[4] = NULL;
	program_environment[5] = NULL;

	if (argc < 4) {
		fprintf(stderr, "usage: secure-wrap <id> <directory> <program> [<args>...]\n");

		return(2);
	}

	id_string = argv[1];
................................................................................
	 **/
	limit.rlim_cur = 0;
	limit.rlim_max = 0;
	check(setrlimit(RLIMIT_CORE, &limit));
	check(setrlimit(RLIMIT_LOCKS, &limit));
	check(setrlimit(RLIMIT_MEMLOCK, &limit));
	check(setrlimit(RLIMIT_MSGQUEUE, &limit));
	check(setrlimit(RLIMIT_FSIZE, &limit));

	/**
	 ** Allow a reasonable number of file descriptors
	 **/
	limit.rlim_cur = 16;
	limit.rlim_max = 16;
	check(setrlimit(RLIMIT_NOFILE, &limit));

	/**
	 ** Allow a reasonable number of processes
	 **/
	limit.rlim_cur = 5;
	limit.rlim_max = 5;
	check(setrlimit(RLIMIT_NPROC, &limit));

	/**
	 ** Allow a reasonable amount of CPU time
	 **/
	limit.rlim_cur = 90;
	limit.rlim_max = 90;
................................................................................
	check(setuid(SECURE_WRAP_BASE_ID + id));

	/*
	 * Install seccomp filter
	 */
	check(enable_seccomp());

	/*
	 * Allow a user-specified HOME directory to be set
	 */
	secure_home = getenv("SECURE_WRAP_HOME");
	if (secure_home) {
		secure_home = strdup(secure_home - 5);

		if (secure_home) {
			program_environment[0] = secure_home;

			if (memcmp(program_environment[0], "HOME=", 5) != 0) {
				return(5);
			}
		}
	}

	/*
	 * Allow a user-specified USER variable to be set
	 */
	secure_user = getenv("SECURE_WRAP_USER");
	if (secure_user) {
		secure_user = strdup(secure_user - 5);

		if (secure_user) {
			program_environment[4] = secure_user;

			if (memcmp(program_environment[4], "USER=", 5) != 0) {
				return(6);
			}
		}
	}

	/*
	 * Execute program
	 */
	check(execve(program, argv, program_environment));

	/*
	 * Failed to execute program
	 */
	return(1);
}




>
>







 







>
>







 







<
<





<
<
<
<
<
<
<







 







<




|
|





|
|







 








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|






1
2
3
4
5
6
7
8
9
10
11
12
13
..
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
44
45
46
47
48
49
50


51
52
53
54
55







56
57
58
59
60
61
62
...
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
157
158
159
160
161
162
163
164
































165
166
167
168
169
170
171
172
173
/*
 * Simple wrapper that does chroot, seccomp,
 * and sets resource limits, before dropping privileges
 */

#define _XOPEN_SOURCE 1

#include <linux/seccomp.h>
#include <linux/filter.h>
#include <sys/resource.h>
#include <linux/audit.h>
#include <sys/ptrace.h>
#include <sys/socket.h>
................................................................................
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <errno.h>
#include <stdio.h>

extern char **environ;

#define SECURE_WRAP_MAX_ID 5242880LU
#define SECURE_WRAP_BASE_ID (1024LU * 1024LU)

#define check(command) if ((command) != 0) { perror(#command); return(1); }

#define error_eperm 1
................................................................................
	check(prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &filter));

	return(0);
}

int main(int argc, char **argv) {
	const char *directory, *program;


	char *id_string;
	unsigned long id;
	struct rlimit limit;
	unsigned int tmp_fd;








	if (argc < 4) {
		fprintf(stderr, "usage: secure-wrap <id> <directory> <program> [<args>...]\n");

		return(2);
	}

	id_string = argv[1];
................................................................................
	 **/
	limit.rlim_cur = 0;
	limit.rlim_max = 0;
	check(setrlimit(RLIMIT_CORE, &limit));
	check(setrlimit(RLIMIT_LOCKS, &limit));
	check(setrlimit(RLIMIT_MEMLOCK, &limit));
	check(setrlimit(RLIMIT_MSGQUEUE, &limit));


	/**
	 ** Allow a reasonable number of file descriptors
	 **/
	limit.rlim_cur = 32;
	limit.rlim_max = 32;
	check(setrlimit(RLIMIT_NOFILE, &limit));

	/**
	 ** Allow a reasonable number of processes
	 **/
	limit.rlim_cur = 10;
	limit.rlim_max = 10;
	check(setrlimit(RLIMIT_NPROC, &limit));

	/**
	 ** Allow a reasonable amount of CPU time
	 **/
	limit.rlim_cur = 90;
	limit.rlim_max = 90;
................................................................................
	check(setuid(SECURE_WRAP_BASE_ID + id));

	/*
	 * Install seccomp filter
	 */
	check(enable_seccomp());

	/*
































	 * Execute program
	 */
	check(execve(program, argv, environ));

	/*
	 * Failed to execute program
	 */
	return(1);
}