| Commit | Line | Data |
|---|---|---|
| 984263bc MD |
1 | /*- |
| 2 | * Copyright (c) 2001 The FreeBSD Project | |
| 3 | * All rights reserved. | |
| 4 | * | |
| 5 | * Redistribution and use in source and binary forms, with or without | |
| 6 | * modification, are permitted provided that the following conditions | |
| 7 | * are met: | |
| 8 | * 1. Redistributions of source code must retain the above copyright | |
| 9 | * notice, this list of conditions and the following disclaimer. | |
| 10 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 11 | * notice, this list of conditions and the following disclaimer in the | |
| 12 | * documentation and/or other materials provided with the distribution. | |
| 13 | * | |
| 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
| 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
| 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 24 | * SUCH DAMAGE. | |
| 25 | * | |
| 26 | * $FreeBSD: src/sys/compat/linux/linux_uid16.c,v 1.4.2.1 2001/10/21 03:57:35 marcel Exp $ | |
| 26be20a0 | 27 | * $DragonFly: src/sys/emulation/linux/linux_uid16.c,v 1.12 2006/12/23 00:27:02 swildner Exp $ |
| 984263bc MD |
28 | */ |
| 29 | ||
| 30 | #include "opt_compat.h" | |
| 31 | ||
| 32 | #include <sys/param.h> | |
| 33 | #include <sys/systm.h> | |
| 136178b3 | 34 | #include <sys/kern_syscall.h> |
| fad57d0e | 35 | #include <sys/nlookup.h> |
| 984263bc | 36 | #include <sys/proc.h> |
| 895c1f85 | 37 | #include <sys/priv.h> |
| 984263bc | 38 | #include <sys/sysproto.h> |
| 136178b3 | 39 | #include <sys/thread.h> |
| 984263bc | 40 | |
| 932f49b9 MD |
41 | #include <arch_linux/linux.h> |
| 42 | #include <arch_linux/linux_proto.h> | |
| 1f2de5d4 | 43 | #include "linux_util.h" |
| 984263bc MD |
44 | |
| 45 | DUMMY(setfsuid16); | |
| 46 | DUMMY(setfsgid16); | |
| 47 | DUMMY(getresuid16); | |
| 48 | DUMMY(getresgid16); | |
| 49 | ||
| 136178b3 | 50 | #define CAST_NOCHG(x) ((x == 0xFFFF) ? -1 : x) |
| 984263bc | 51 | |
| 3919ced0 MD |
52 | /* |
| 53 | * MPALMOSTSAFE | |
| 54 | */ | |
| 984263bc | 55 | int |
| 753fd850 | 56 | sys_linux_chown16(struct linux_chown16_args *args) |
| 984263bc | 57 | { |
| fad57d0e | 58 | struct nlookupdata nd; |
| 136178b3 | 59 | char *path; |
| 90b9818c | 60 | int error; |
| 984263bc | 61 | |
| 136178b3 DRJ |
62 | error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS); |
| 63 | if (error) | |
| 64 | return (error); | |
| 984263bc MD |
65 | #ifdef DEBUG |
| 66 | if (ldebug(chown16)) | |
| 26be20a0 | 67 | kprintf(ARGS(chown16, "%s, %d, %d"), path, args->uid, |
| 984263bc MD |
68 | args->gid); |
| 69 | #endif | |
| 3919ced0 | 70 | get_mplock(); |
| fad57d0e MD |
71 | error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW); |
| 72 | if (error == 0) { | |
| 73 | error = kern_chown(&nd, CAST_NOCHG(args->uid), | |
| 74 | CAST_NOCHG(args->gid)); | |
| 75 | } | |
| 76 | nlookup_done(&nd); | |
| 3919ced0 | 77 | rel_mplock(); |
| 136178b3 | 78 | linux_free_path(&path); |
| 90b9818c | 79 | return(error); |
| 984263bc MD |
80 | } |
| 81 | ||
| 3919ced0 MD |
82 | /* |
| 83 | * MPALMOSTSAFE | |
| 84 | */ | |
| 984263bc | 85 | int |
| 753fd850 | 86 | sys_linux_lchown16(struct linux_lchown16_args *args) |
| 984263bc | 87 | { |
| fad57d0e | 88 | struct nlookupdata nd; |
| 136178b3 | 89 | char *path; |
| 90b9818c | 90 | int error; |
| 984263bc | 91 | |
| 136178b3 DRJ |
92 | error = linux_copyin_path(args->path, &path, LINUX_PATH_EXISTS); |
| 93 | if (error) | |
| 94 | return (error); | |
| 984263bc MD |
95 | #ifdef DEBUG |
| 96 | if (ldebug(lchown16)) | |
| 26be20a0 | 97 | kprintf(ARGS(lchown16, "%s, %d, %d"), path, args->uid, |
| 984263bc MD |
98 | args->gid); |
| 99 | #endif | |
| 3919ced0 | 100 | get_mplock(); |
| fad57d0e MD |
101 | error = nlookup_init(&nd, path, UIO_SYSSPACE, 0); |
| 102 | if (error == 0) { | |
| 103 | error = kern_chown(&nd, CAST_NOCHG(args->uid), | |
| 104 | CAST_NOCHG(args->gid)); | |
| 105 | } | |
| 106 | nlookup_done(&nd); | |
| 3919ced0 | 107 | rel_mplock(); |
| 136178b3 | 108 | linux_free_path(&path); |
| 90b9818c | 109 | return(error); |
| 984263bc MD |
110 | } |
| 111 | ||
| 3919ced0 MD |
112 | /* |
| 113 | * MPALMOSTSAFE | |
| 114 | */ | |
| 984263bc | 115 | int |
| 753fd850 | 116 | sys_linux_setgroups16(struct linux_setgroups16_args *args) |
| 984263bc | 117 | { |
| 9910d07b MD |
118 | struct thread *td = curthread; |
| 119 | struct proc *p = td->td_proc; | |
| 984263bc MD |
120 | struct ucred *newcred, *oldcred; |
| 121 | l_gid16_t linux_gidset[NGROUPS]; | |
| 122 | gid_t *bsd_gidset; | |
| 123 | int ngrp, error; | |
| 124 | ||
| 125 | #ifdef DEBUG | |
| 126 | if (ldebug(setgroups16)) | |
| 26be20a0 | 127 | kprintf(ARGS(setgroups16, "%d, *"), args->gidsetsize); |
| 984263bc MD |
128 | #endif |
| 129 | ||
| 130 | ngrp = args->gidsetsize; | |
| 9910d07b | 131 | oldcred = td->td_ucred; |
| 984263bc MD |
132 | |
| 133 | /* | |
| 134 | * cr_groups[0] holds egid. Setting the whole set from | |
| 135 | * the supplied set will cause egid to be changed too. | |
| 136 | * Keep cr_groups[0] unchanged to prevent that. | |
| 137 | */ | |
| 138 | ||
| 741fa32c | 139 | if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) |
| 984263bc MD |
140 | return (error); |
| 141 | ||
| 3919ced0 | 142 | if ((u_int)ngrp >= NGROUPS) |
| 984263bc MD |
143 | return (EINVAL); |
| 144 | ||
| 3919ced0 | 145 | get_mplock(); |
| 984263bc MD |
146 | newcred = crdup(oldcred); |
| 147 | if (ngrp > 0) { | |
| 148 | error = copyin((caddr_t)args->gidset, linux_gidset, | |
| da311c9d MD |
149 | ngrp * sizeof(l_gid16_t)); |
| 150 | if (error) { | |
| 151 | crfree(newcred); | |
| 3919ced0 | 152 | goto done; |
| da311c9d | 153 | } |
| 984263bc MD |
154 | |
| 155 | newcred->cr_ngroups = ngrp + 1; | |
| 156 | ||
| 157 | bsd_gidset = newcred->cr_groups; | |
| 158 | ngrp--; | |
| 159 | while (ngrp >= 0) { | |
| 160 | bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; | |
| 161 | ngrp--; | |
| 162 | } | |
| da311c9d | 163 | } else { |
| 984263bc | 164 | newcred->cr_ngroups = 1; |
| da311c9d | 165 | } |
| 984263bc | 166 | |
| 41c20dac | 167 | setsugid(); |
| 9910d07b | 168 | oldcred = p->p_ucred; /* deal with threads race */ |
| 984263bc MD |
169 | p->p_ucred = newcred; |
| 170 | crfree(oldcred); | |
| 3919ced0 MD |
171 | error = 0; |
| 172 | done: | |
| 173 | rel_mplock(); | |
| 174 | return (error); | |
| 984263bc MD |
175 | } |
| 176 | ||
| 3919ced0 MD |
177 | /* |
| 178 | * MPSAFE | |
| 179 | */ | |
| 984263bc | 180 | int |
| 753fd850 | 181 | sys_linux_getgroups16(struct linux_getgroups16_args *args) |
| 984263bc | 182 | { |
| 41c20dac | 183 | struct proc *p = curproc; |
| 984263bc MD |
184 | struct ucred *cred; |
| 185 | l_gid16_t linux_gidset[NGROUPS]; | |
| 186 | gid_t *bsd_gidset; | |
| 187 | int bsd_gidsetsz, ngrp, error; | |
| 188 | ||
| 189 | #ifdef DEBUG | |
| 190 | if (ldebug(getgroups16)) | |
| 26be20a0 | 191 | kprintf(ARGS(getgroups16, "%d, *"), args->gidsetsize); |
| 984263bc MD |
192 | #endif |
| 193 | ||
| 194 | cred = p->p_ucred; | |
| 195 | bsd_gidset = cred->cr_groups; | |
| 196 | bsd_gidsetsz = cred->cr_ngroups - 1; | |
| 197 | ||
| 198 | /* | |
| 199 | * cr_groups[0] holds egid. Returning the whole set | |
| 200 | * here will cause a duplicate. Exclude cr_groups[0] | |
| 201 | * to prevent that. | |
| 202 | */ | |
| 203 | ||
| 204 | if ((ngrp = args->gidsetsize) == 0) { | |
| c7114eea | 205 | args->sysmsg_result = bsd_gidsetsz; |
| 984263bc MD |
206 | return (0); |
| 207 | } | |
| 208 | ||
| 3919ced0 | 209 | if ((u_int)ngrp < (u_int)bsd_gidsetsz) |
| 984263bc MD |
210 | return (EINVAL); |
| 211 | ||
| 212 | ngrp = 0; | |
| 213 | while (ngrp < bsd_gidsetsz) { | |
| 214 | linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; | |
| 215 | ngrp++; | |
| 216 | } | |
| 217 | ||
| 218 | error = copyout(linux_gidset, (caddr_t)args->gidset, | |
| 3919ced0 | 219 | ngrp * sizeof(l_gid16_t)); |
| 984263bc MD |
220 | if (error) |
| 221 | return (error); | |
| 222 | ||
| c7114eea | 223 | args->sysmsg_result = ngrp; |
| 984263bc MD |
224 | return (0); |
| 225 | } | |
| 226 | ||
| 227 | /* | |
| 228 | * The FreeBSD native getgid(2) and getuid(2) also modify p->p_retval[1] | |
| 229 | * when COMPAT_43 or COMPAT_SUNOS is defined. This globbers registers that | |
| 230 | * are assumed to be preserved. The following lightweight syscalls fixes | |
| 231 | * this. See also linux_getpid(2), linux_getgid(2) and linux_getuid(2) in | |
| 232 | * linux_misc.c | |
| 233 | * | |
| 234 | * linux_getgid16() - MP SAFE | |
| 235 | * linux_getuid16() - MP SAFE | |
| 236 | */ | |
| 237 | ||
| 3919ced0 MD |
238 | /* |
| 239 | * MPSAFE | |
| 240 | */ | |
| 984263bc | 241 | int |
| 753fd850 | 242 | sys_linux_getgid16(struct linux_getgid16_args *args) |
| 984263bc | 243 | { |
| 41c20dac | 244 | struct proc *p = curproc; |
| 984263bc | 245 | |
| c7114eea | 246 | args->sysmsg_result = p->p_ucred->cr_rgid; |
| 984263bc MD |
247 | return (0); |
| 248 | } | |
| 249 | ||
| 3919ced0 MD |
250 | /* |
| 251 | * MPSAFE | |
| 252 | */ | |
| 984263bc | 253 | int |
| 753fd850 | 254 | sys_linux_getuid16(struct linux_getuid16_args *args) |
| 984263bc | 255 | { |
| 41c20dac | 256 | struct proc *p = curproc; |
| 984263bc | 257 | |
| c7114eea | 258 | args->sysmsg_result = p->p_ucred->cr_ruid; |
| 984263bc MD |
259 | return (0); |
| 260 | } | |
| 261 | ||
| 3919ced0 MD |
262 | /* |
| 263 | * MPSAFE | |
| 264 | */ | |
| 984263bc | 265 | int |
| 753fd850 | 266 | sys_linux_getegid16(struct linux_getegid16_args *args) |
| 984263bc MD |
267 | { |
| 268 | struct getegid_args bsd; | |
| 90b9818c MD |
269 | int error; |
| 270 | ||
| c7114eea | 271 | bsd.sysmsg_result = 0; |
| 984263bc | 272 | |
| 753fd850 | 273 | error = sys_getegid(&bsd); |
| c7114eea | 274 | args->sysmsg_result = bsd.sysmsg_result; |
| 90b9818c | 275 | return(error); |
| 984263bc MD |
276 | } |
| 277 | ||
| 3919ced0 MD |
278 | /* |
| 279 | * MPSAFE | |
| 280 | */ | |
| 984263bc | 281 | int |
| 753fd850 | 282 | sys_linux_geteuid16(struct linux_geteuid16_args *args) |
| 984263bc MD |
283 | { |
| 284 | struct geteuid_args bsd; | |
| 90b9818c MD |
285 | int error; |
| 286 | ||
| c7114eea | 287 | bsd.sysmsg_result = 0; |
| 984263bc | 288 | |
| 753fd850 | 289 | error = sys_geteuid(&bsd); |
| c7114eea | 290 | args->sysmsg_result = bsd.sysmsg_result; |
| 90b9818c | 291 | return(error); |
| 984263bc MD |
292 | } |
| 293 | ||
| 3919ced0 MD |
294 | /* |
| 295 | * MPSAFE | |
| 296 | */ | |
| 984263bc | 297 | int |
| 753fd850 | 298 | sys_linux_setgid16(struct linux_setgid16_args *args) |
| 984263bc MD |
299 | { |
| 300 | struct setgid_args bsd; | |
| 90b9818c | 301 | int error; |
| 984263bc MD |
302 | |
| 303 | bsd.gid = args->gid; | |
| c7114eea | 304 | bsd.sysmsg_result = 0; |
| 90b9818c | 305 | |
| 753fd850 | 306 | error = sys_setgid(&bsd); |
| c7114eea | 307 | args->sysmsg_result = bsd.sysmsg_result; |
| 90b9818c | 308 | return(error); |
| 984263bc MD |
309 | } |
| 310 | ||
| 3919ced0 MD |
311 | /* |
| 312 | * MPSAFE | |
| 313 | */ | |
| 984263bc | 314 | int |
| 753fd850 | 315 | sys_linux_setuid16(struct linux_setuid16_args *args) |
| 984263bc MD |
316 | { |
| 317 | struct setuid_args bsd; | |
| 90b9818c | 318 | int error; |
| 984263bc MD |
319 | |
| 320 | bsd.uid = args->uid; | |
| c7114eea | 321 | bsd.sysmsg_result = 0; |
| 90b9818c | 322 | |
| 753fd850 | 323 | error = sys_setuid(&bsd); |
| c7114eea | 324 | args->sysmsg_result = bsd.sysmsg_result; |
| 90b9818c | 325 | return(error); |
| 984263bc MD |
326 | } |
| 327 | ||
| 3919ced0 MD |
328 | /* |
| 329 | * MPSAFE | |
| 330 | */ | |
| 984263bc | 331 | int |
| 753fd850 | 332 | sys_linux_setregid16(struct linux_setregid16_args *args) |
| 984263bc MD |
333 | { |
| 334 | struct setregid_args bsd; | |
| 90b9818c | 335 | int error; |
| 984263bc MD |
336 | |
| 337 | bsd.rgid = CAST_NOCHG(args->rgid); | |
| 338 | bsd.egid = CAST_NOCHG(args->egid); | |
| c7114eea | 339 | bsd.sysmsg_result = 0; |
| 90b9818c | 340 | |
| 753fd850 | 341 | error = sys_setregid(&bsd); |
| c7114eea | 342 | args->sysmsg_result = bsd.sysmsg_result; |
| 90b9818c | 343 | return(error); |
| 984263bc MD |
344 | } |
| 345 | ||
| 3919ced0 MD |
346 | /* |
| 347 | * MPSAFE | |
| 348 | */ | |
| 984263bc | 349 | int |
| 753fd850 | 350 | sys_linux_setreuid16(struct linux_setreuid16_args *args) |
| 984263bc MD |
351 | { |
| 352 | struct setreuid_args bsd; | |
| 90b9818c | 353 | int error; |
| 984263bc MD |
354 | |
| 355 | bsd.ruid = CAST_NOCHG(args->ruid); | |
| 356 | bsd.euid = CAST_NOCHG(args->euid); | |
| c7114eea | 357 | bsd.sysmsg_result = 0; |
| 90b9818c | 358 | |
| 753fd850 | 359 | error = sys_setreuid(&bsd); |
| c7114eea | 360 | args->sysmsg_result = bsd.sysmsg_result; |
| 90b9818c | 361 | return(error); |
| 984263bc MD |
362 | } |
| 363 | ||
| 3919ced0 MD |
364 | /* |
| 365 | * MPSAFE | |
| 366 | */ | |
| 984263bc | 367 | int |
| 753fd850 | 368 | sys_linux_setresgid16(struct linux_setresgid16_args *args) |
| 984263bc MD |
369 | { |
| 370 | struct setresgid_args bsd; | |
| 90b9818c | 371 | int error; |
| 984263bc MD |
372 | |
| 373 | bsd.rgid = CAST_NOCHG(args->rgid); | |
| 374 | bsd.egid = CAST_NOCHG(args->egid); | |
| 375 | bsd.sgid = CAST_NOCHG(args->sgid); | |
| c7114eea | 376 | bsd.sysmsg_result = 0; |
| 90b9818c | 377 | |
| 753fd850 | 378 | error = sys_setresgid(&bsd); |
| c7114eea | 379 | args->sysmsg_result = bsd.sysmsg_result; |
| 90b9818c | 380 | return(error); |
| 984263bc MD |
381 | } |
| 382 | ||
| 3919ced0 MD |
383 | /* |
| 384 | * MPSAFE | |
| 385 | */ | |
| 984263bc | 386 | int |
| 753fd850 | 387 | sys_linux_setresuid16(struct linux_setresuid16_args *args) |
| 984263bc MD |
388 | { |
| 389 | struct setresuid_args bsd; | |
| 90b9818c | 390 | int error; |
| 984263bc MD |
391 | |
| 392 | bsd.ruid = CAST_NOCHG(args->ruid); | |
| 393 | bsd.euid = CAST_NOCHG(args->euid); | |
| 394 | bsd.suid = CAST_NOCHG(args->suid); | |
| c7114eea | 395 | bsd.sysmsg_result = 0; |
| 90b9818c | 396 | |
| 753fd850 | 397 | error = sys_setresuid(&bsd); |
| c7114eea | 398 | args->sysmsg_result = bsd.sysmsg_result; |
| 90b9818c | 399 | return(error); |
| 984263bc | 400 | } |
| 90b9818c | 401 |