1 /* $NetBSD: linux_misc_notalpha.c,v 1.111 2020/12/04 00:26:16 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998, 2008, 2020 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe 9 * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.111 2020/12/04 00:26:16 thorpej Exp $"); 35 36 /* 37 * Note that we must NOT include "opt_compat_linux32.h" here, 38 * the maze of ifdefs below relies on COMPAT_LINUX32 only being 39 * defined when this file is built for linux32. 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/mman.h> 46 #include <sys/mount.h> 47 #include <sys/mbuf.h> 48 #include <sys/namei.h> 49 #include <sys/proc.h> 50 #include <sys/prot.h> 51 #include <sys/ptrace.h> 52 #include <sys/resource.h> 53 #include <sys/resourcevar.h> 54 #include <sys/time.h> 55 #include <sys/vfs_syscalls.h> 56 #include <sys/wait.h> 57 #include <sys/kauth.h> 58 59 #include <sys/syscallargs.h> 60 61 #include <compat/linux/common/linux_types.h> 62 #include <compat/linux/common/linux_fcntl.h> 63 #include <compat/linux/common/linux_misc.h> 64 #include <compat/linux/common/linux_mmap.h> 65 #include <compat/linux/common/linux_signal.h> 66 #include <compat/linux/common/linux_util.h> 67 #include <compat/linux/common/linux_ipc.h> 68 #include <compat/linux/common/linux_sem.h> 69 #include <compat/linux/common/linux_statfs.h> 70 71 #include <compat/linux/linux_syscallargs.h> 72 73 /* 74 * This file contains routines which are used 75 * on every linux architechture except the Alpha. 76 */ 77 78 /* Used on: arm, i386, m68k, mips, ppc, sparc, sparc64 */ 79 /* Not used on: alpha */ 80 81 #ifdef DEBUG_LINUX 82 #define DPRINTF(a) uprintf a 83 #else 84 #define DPRINTF(a) 85 #endif 86 87 #ifndef COMPAT_LINUX32 88 89 /* 90 * Alarm. This is a libc call which uses setitimer(2) in NetBSD. 91 * Do the same here. 92 */ 93 int 94 linux_sys_alarm(struct lwp *l, const struct linux_sys_alarm_args *uap, register_t *retval) 95 { 96 /* { 97 syscallarg(unsigned int) secs; 98 } */ 99 struct proc *p = l->l_proc; 100 struct itimerval itv, oitv; 101 int error; 102 103 timerclear(&itv.it_interval); 104 itv.it_value.tv_sec = SCARG(uap, secs); 105 itv.it_value.tv_usec = 0; 106 if (itv.it_value.tv_sec < 0) { 107 return EINVAL; 108 } 109 110 if ((error = dogetitimer(p, ITIMER_REAL, &oitv)) != 0) { 111 return error; 112 } 113 if (oitv.it_value.tv_usec) { 114 oitv.it_value.tv_sec++; 115 } 116 117 if ((error = dosetitimer(p, ITIMER_REAL, &itv)) != 0) { 118 return error; 119 } 120 121 *retval = oitv.it_value.tv_sec; 122 return 0; 123 } 124 #endif /* !COMPAT_LINUX32 */ 125 126 #if !defined(__amd64__) 127 int 128 linux_sys_nice(struct lwp *l, const struct linux_sys_nice_args *uap, register_t *retval) 129 { 130 /* { 131 syscallarg(int) incr; 132 } */ 133 struct proc *p = l->l_proc; 134 struct sys_setpriority_args bsa; 135 int error; 136 137 SCARG(&bsa, which) = PRIO_PROCESS; 138 SCARG(&bsa, who) = 0; 139 SCARG(&bsa, prio) = p->p_nice - NZERO + SCARG(uap, incr); 140 141 error = sys_setpriority(l, &bsa, retval); 142 return (error) ? EPERM : 0; 143 } 144 #endif /* !__amd64__ */ 145 146 #ifndef COMPAT_LINUX32 147 #ifndef __amd64__ 148 /* 149 * The old Linux readdir was only able to read one entry at a time, 150 * even though it had a 'count' argument. In fact, the emulation 151 * of the old call was better than the original, because it did handle 152 * the count arg properly. Don't bother with it anymore now, and use 153 * it to distinguish between old and new. The difference is that the 154 * newer one actually does multiple entries, and the reclen field 155 * really is the reclen, not the namelength. 156 */ 157 int 158 linux_sys_readdir(struct lwp *l, const struct linux_sys_readdir_args *uap, register_t *retval) 159 { 160 /* { 161 syscallarg(int) fd; 162 syscallarg(struct linux_dirent *) dent; 163 syscallarg(unsigned int) count; 164 } */ 165 int error; 166 struct linux_sys_getdents_args da; 167 168 SCARG(&da, fd) = SCARG(uap, fd); 169 SCARG(&da, dent) = SCARG(uap, dent); 170 SCARG(&da, count) = 1; 171 172 error = linux_sys_getdents(l, &da, retval); 173 if (error == 0 && *retval > 1) 174 *retval = 1; 175 176 return error; 177 } 178 #endif /* !amd64 */ 179 180 /* 181 * I wonder why Linux has gettimeofday() _and_ time().. Still, we 182 * need to deal with it. 183 */ 184 int 185 linux_sys_time(struct lwp *l, const struct linux_sys_time_args *uap, register_t *retval) 186 { 187 /* { 188 syscallarg(linux_time_t) *t; 189 } */ 190 struct timeval atv; 191 linux_time_t tt; 192 int error; 193 194 microtime(&atv); 195 196 tt = atv.tv_sec; 197 if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt))) 198 return error; 199 200 retval[0] = tt; 201 return 0; 202 } 203 204 /* 205 * utime(). Do conversion to things that utimes() understands, 206 * and pass it on. 207 */ 208 int 209 linux_sys_utime(struct lwp *l, const struct linux_sys_utime_args *uap, register_t *retval) 210 { 211 /* { 212 syscallarg(const char *) path; 213 syscallarg(struct linux_utimbuf *)times; 214 } */ 215 int error; 216 struct timeval tv[2], *tvp; 217 struct linux_utimbuf lut; 218 219 if (SCARG(uap, times) != NULL) { 220 if ((error = copyin(SCARG(uap, times), &lut, sizeof lut))) 221 return error; 222 tv[0].tv_usec = tv[1].tv_usec = 0; 223 tv[0].tv_sec = lut.l_actime; 224 tv[1].tv_sec = lut.l_modtime; 225 tvp = tv; 226 } else 227 tvp = NULL; 228 229 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW, 230 tvp, UIO_SYSSPACE); 231 } 232 233 #ifndef __amd64__ 234 /* 235 * waitpid(2). Just forward on to linux_sys_wait4 with a NULL rusage. 236 */ 237 int 238 linux_sys_waitpid(struct lwp *l, const struct linux_sys_waitpid_args *uap, register_t *retval) 239 { 240 /* { 241 syscallarg(int) pid; 242 syscallarg(int *) status; 243 syscallarg(int) options; 244 } */ 245 struct linux_sys_wait4_args linux_w4a; 246 247 SCARG(&linux_w4a, pid) = SCARG(uap, pid); 248 SCARG(&linux_w4a, status) = SCARG(uap, status); 249 SCARG(&linux_w4a, options) = SCARG(uap, options); 250 SCARG(&linux_w4a, rusage) = NULL; 251 252 return linux_sys_wait4(l, &linux_w4a, retval); 253 } 254 #endif /* !amd64 */ 255 256 int 257 linux_sys_setresgid(struct lwp *l, const struct linux_sys_setresgid_args *uap, register_t *retval) 258 { 259 /* { 260 syscallarg(gid_t) rgid; 261 syscallarg(gid_t) egid; 262 syscallarg(gid_t) sgid; 263 } */ 264 265 /* 266 * Note: These checks are a little different than the NetBSD 267 * setregid(2) call performs. This precisely follows the 268 * behavior of the Linux kernel. 269 */ 270 return do_setresgid(l, SCARG(uap,rgid), SCARG(uap, egid), 271 SCARG(uap, sgid), 272 ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S | 273 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 274 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S ); 275 } 276 277 int 278 linux_sys_getresgid(struct lwp *l, const struct linux_sys_getresgid_args *uap, register_t *retval) 279 { 280 /* { 281 syscallarg(gid_t *) rgid; 282 syscallarg(gid_t *) egid; 283 syscallarg(gid_t *) sgid; 284 } */ 285 kauth_cred_t pc = l->l_cred; 286 int error; 287 gid_t gid; 288 289 /* 290 * Linux copies these values out to userspace like so: 291 * 292 * 1. Copy out rgid. 293 * 2. If that succeeds, copy out egid. 294 * 3. If both of those succeed, copy out sgid. 295 */ 296 gid = kauth_cred_getgid(pc); 297 if ((error = copyout(&gid, SCARG(uap, rgid), sizeof(gid_t))) != 0) 298 return (error); 299 300 gid = kauth_cred_getegid(pc); 301 if ((error = copyout(&gid, SCARG(uap, egid), sizeof(gid_t))) != 0) 302 return (error); 303 304 gid = kauth_cred_getsvgid(pc); 305 306 return (copyout(&gid, SCARG(uap, sgid), sizeof(gid_t))); 307 } 308 309 #ifndef __amd64__ 310 /* 311 * I wonder why Linux has settimeofday() _and_ stime().. Still, we 312 * need to deal with it. 313 */ 314 int 315 linux_sys_stime(struct lwp *l, const struct linux_sys_stime_args *uap, register_t *retval) 316 { 317 /* { 318 syscallarg(linux_time_t) *t; 319 } */ 320 struct timespec ats; 321 linux_time_t tt; 322 int error; 323 324 if ((error = copyin(SCARG(uap, t), &tt, sizeof tt)) != 0) 325 return error; 326 327 ats.tv_sec = tt; 328 ats.tv_nsec = 0; 329 330 if ((error = settime(l->l_proc, &ats))) 331 return (error); 332 333 return 0; 334 } 335 336 /* 337 * Implement the fs stat functions. Straightforward. 338 */ 339 int 340 linux_sys_statfs64(struct lwp *l, const struct linux_sys_statfs64_args *uap, register_t *retval) 341 { 342 /* { 343 syscallarg(const char *) path; 344 syscallarg(size_t) sz; 345 syscallarg(struct linux_statfs64 *) sp; 346 } */ 347 struct statvfs *sb; 348 struct linux_statfs64 ltmp; 349 int error; 350 351 if (SCARG(uap, sz) != sizeof ltmp) 352 return (EINVAL); 353 354 sb = STATVFSBUF_GET(); 355 error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb); 356 if (error == 0) { 357 bsd_to_linux_statfs64(sb, <mp); 358 error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 359 } 360 STATVFSBUF_PUT(sb); 361 return error; 362 } 363 364 int 365 linux_sys_fstatfs64(struct lwp *l, const struct linux_sys_fstatfs64_args *uap, register_t *retval) 366 { 367 /* { 368 syscallarg(int) fd; 369 syscallarg(size_t) sz; 370 syscallarg(struct linux_statfs64 *) sp; 371 } */ 372 struct statvfs *sb; 373 struct linux_statfs64 ltmp; 374 int error; 375 376 if (SCARG(uap, sz) != sizeof ltmp) 377 return (EINVAL); 378 379 sb = STATVFSBUF_GET(); 380 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb); 381 if (error == 0) { 382 bsd_to_linux_statfs64(sb, <mp); 383 error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 384 } 385 STATVFSBUF_PUT(sb); 386 return error; 387 } 388 #endif /* !__amd64__ */ 389 #endif /* !COMPAT_LINUX32 */ 390