kernel - use new td_ucred in numerous places
[dragonfly.git] / sys / emulation / linux / linux_uid16.c
CommitLineData
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
45DUMMY(setfsuid16);
46DUMMY(setfsgid16);
47DUMMY(getresuid16);
48DUMMY(getresgid16);
49
136178b3 50#define CAST_NOCHG(x) ((x == 0xFFFF) ? -1 : x)
984263bc 51
3919ced0
MD
52/*
53 * MPALMOSTSAFE
54 */
984263bc 55int
753fd850 56sys_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 85int
753fd850 86sys_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 115int
753fd850 116sys_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;
172done:
173 rel_mplock();
174 return (error);
984263bc
MD
175}
176
3919ced0
MD
177/*
178 * MPSAFE
179 */
984263bc 180int
753fd850 181sys_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 241int
753fd850 242sys_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 253int
753fd850 254sys_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 265int
753fd850 266sys_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 281int
753fd850 282sys_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 297int
753fd850 298sys_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 314int
753fd850 315sys_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 331int
753fd850 332sys_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 349int
753fd850 350sys_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 367int
753fd850 368sys_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 386int
753fd850 387sys_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