xref: /aosp_15_r20/external/mtools/privileges.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1 /*  Copyright 1997,1999,2001,2002,2007,2009 Alain Knaff.
2  *  This file is part of mtools.
3  *
4  *  Mtools is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  Mtools is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "sysincludes.h"
19 #include "msdos.h"
20 #include "mtools.h"
21 
22 int noPrivileges=0;
23 
24 #ifdef OS_mingw32msvc
reclaim_privs(void)25 void reclaim_privs(void)
26 {
27 }
28 
drop_privs(void)29 void drop_privs(void)
30 {
31 }
32 
destroy_privs(void)33 void destroy_privs(void)
34 {
35 }
36 
get_real_uid(void)37 uid_t get_real_uid(void)
38 {
39 	return 0;
40 }
41 
init_privs(void)42 void init_privs(void)
43 {
44 }
45 
closeExec(int fd)46 void closeExec(int fd)
47 {
48 }
49 
50 #else
51 /*#define PRIV_DEBUG*/
52 
53 #if 0
54 #undef HAVE_SETEUID
55 #define HAVE_SETRESUID
56 #include <asm/unistd.h>
57 int setresuid(int a, int b, int c)
58 {
59 	syscall(164, a, b, c);
60 
61 }
62 #endif
63 
print_privs(const char * message UNUSEDP)64 static __inline__ void print_privs(const char *message UNUSEDP)
65 {
66 #ifdef PRIV_DEBUG
67 	/* for debugging purposes only */
68 	fprintf(stderr,"%s egid=%d rgid=%d\n", message, getegid(), getgid());
69 	fprintf(stderr,"%s euid=%d ruid=%d\n", message, geteuid(), getuid());
70 #endif
71 }
72 
73 
74 static gid_t rgid, egid;
75 static uid_t ruid, euid;
76 
77 /* privilege management routines for SunOS and Solaris.  These are
78  * needed in order to issue raw SCSI read/write ioctls.  Mtools drops
79  * its privileges at the beginning, and reclaims them just for the
80  * above-mentioned ioctl's.  Before popen(), exec() or system, it
81  * drops its privileges completely, and issues a warning.
82  */
83 
84 
85 /* group id handling is lots easier, as long as we don't use group 0.
86  * If you want to use group id's, create a *new* group mtools or
87  * floppy.  Chgrp any devices that you only want to be accessible to
88  * mtools to this group, and give them the appropriate privs.  Make
89  * sure this group doesn't own any other files: be aware that any user
90  * with access to mtools may mformat these files!
91  */
92 
93 
Setuid(uid_t uid)94 static __inline__ void Setuid(uid_t uid)
95 {
96 #if defined HAVE_SETEUID || defined HAVE_SETRESUID
97 	if(euid == 0) {
98 #ifdef HAVE_SETEUID
99 		seteuid(uid);
100 #else
101 		setresuid(ruid, uid, euid);
102 #endif
103 	} else
104 #endif
105 		setuid(uid);
106 }
107 
108 /* In reclaim_privs and drop privs, we have to manipulate group privileges
109  * when having no root privileges, else we might lose them */
110 
reclaim_privs(void)111 void reclaim_privs(void)
112 {
113 	if(noPrivileges)
114 		return;
115 	setgid(egid);
116 	Setuid(euid);
117 	print_privs("after reclaim privs, both uids should be 0 ");
118 }
119 
drop_privs(void)120 void drop_privs(void)
121 {
122 	Setuid(ruid);
123 	setgid(rgid);
124 	print_privs("after drop_privs, real should be 0, effective should not ");
125 }
126 
destroy_privs(void)127 void destroy_privs(void)
128 {
129 
130 #if defined HAVE_SETEUID || defined HAVE_SETRESUID
131 	if(euid == 0) {
132 #ifdef HAVE_SETEUID
133 		setuid(0); /* get the necessary privs to drop real root id */
134 		setuid(ruid); /* this should be enough to get rid of the three
135 			       * ids */
136 		seteuid(ruid); /* for good measure... just in case we came
137 				* across a system which implemented sane
138 				* semantics instead of POSIXly broken
139 				* semantics for setuid */
140 #else
141 		setresuid(ruid, ruid, ruid);
142 #endif
143 	}
144 #endif
145 
146 	/* we also destroy group privileges */
147 	drop_privs();
148 
149 	/* saved set [ug]id will go away by itself on exec */
150 
151 	print_privs("destroy_privs, no uid should be zero  ");
152 }
153 
154 
get_real_uid(void)155 uid_t get_real_uid(void)
156 {
157 	return ruid;
158 }
159 
init_privs(void)160 void init_privs(void)
161 {
162 	euid = geteuid();
163 	ruid = getuid();
164 	egid = getegid();
165 	rgid = getgid();
166 
167 #ifndef F_SETFD
168 	if(euid != ruid) {
169 		fprintf(stderr,
170 			"Setuid installation not supported on this platform\n");
171 		fprintf(stderr,
172 			"Missing F_SETFD");
173 		exit(1);
174 	}
175 #endif
176 
177 	if(euid != ruid) {
178 		unsetenv("SOURCE_DATE_EPOCH");
179 	}
180 	if(euid == 0 && ruid != 0) {
181 #ifdef HAVE_SETEUID
182 		setuid(0); /* set real uid to 0 */
183 #else
184 #ifndef HAVE_SETRESUID
185 		/* on this machine, it is not possible to reversibly drop
186 		 * root privileges.  We print an error and quit */
187 
188 		/* BEOS is no longer a special case, as both euid and ruid
189 		 * return 0, and thus we do not get any longer into this
190 		 * branch */
191 		fprintf(stderr,
192 			"Seteuid call not supported on this architecture.\n");
193 		fprintf(stderr,
194 			"Mtools cannot be installed setuid root.\n");
195 		fprintf(stderr,
196 			"However, it can be installed setuid to a non root");
197 		fprintf(stderr,
198 			"user or setgid to any id.\n");
199 		exit(1);
200 #endif
201 #endif
202 	}
203 
204 	drop_privs();
205 	print_privs("after init, real should be 0, effective should not ");
206 }
207 
closeExec(int fd)208 void closeExec(int fd)
209 {
210 #ifdef F_SETFD
211 	fcntl(fd, F_SETFD, 1);
212 #endif
213 }
214 #endif
215