1 /* $NetBSD: linux_misc_notalpha.c,v 1.113 2021/09/23 11:28:47 christos 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.113 2021/09/23 11:28:47 christos 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, aarch64, 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 #if !defined(__aarch64__) 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 125 #endif /* !COMPAT_LINUX32 */ 126 127 #if !defined(__aarch64__) && !defined(__amd64__) 128 int 129 linux_sys_nice(struct lwp *l, const struct linux_sys_nice_args *uap, register_t *retval) 130 { 131 /* { 132 syscallarg(int) incr; 133 } */ 134 struct proc *p = l->l_proc; 135 struct sys_setpriority_args bsa; 136 int error; 137 138 SCARG(&bsa, which) = PRIO_PROCESS; 139 SCARG(&bsa, who) = 0; 140 SCARG(&bsa, prio) = p->p_nice - NZERO + SCARG(uap, incr); 141 142 error = sys_setpriority(l, &bsa, retval); 143 return (error) ? EPERM : 0; 144 } 145 #endif /* !__aarch64__ && !__amd64__ */ 146 147 #ifndef COMPAT_LINUX32 148 #if !defined(__aarch64__) && !defined(__amd64__) 149 /* 150 * The old Linux readdir was only able to read one entry at a time, 151 * even though it had a 'count' argument. In fact, the emulation 152 * of the old call was better than the original, because it did handle 153 * the count arg properly. Don't bother with it anymore now, and use 154 * it to distinguish between old and new. The difference is that the 155 * newer one actually does multiple entries, and the reclen field 156 * really is the reclen, not the namelength. 157 */ 158 int 159 linux_sys_readdir(struct lwp *l, const struct linux_sys_readdir_args *uap, register_t *retval) 160 { 161 /* { 162 syscallarg(int) fd; 163 syscallarg(struct linux_dirent *) dent; 164 syscallarg(unsigned int) count; 165 } */ 166 int error; 167 struct linux_sys_getdents_args da; 168 169 SCARG(&da, fd) = SCARG(uap, fd); 170 SCARG(&da, dent) = SCARG(uap, dent); 171 SCARG(&da, count) = 1; 172 173 error = linux_sys_getdents(l, &da, retval); 174 if (error == 0 && *retval > 1) 175 *retval = 1; 176 177 return error; 178 } 179 #endif /* !aarch64 && !amd64 */ 180 181 #if !defined(__aarch64__) 182 /* 183 * I wonder why Linux has gettimeofday() _and_ time().. Still, we 184 * need to deal with it. 185 */ 186 int 187 linux_sys_time(struct lwp *l, const struct linux_sys_time_args *uap, register_t *retval) 188 { 189 /* { 190 syscallarg(linux_time_t) *t; 191 } */ 192 struct timeval atv; 193 linux_time_t tt; 194 int error; 195 196 microtime(&atv); 197 198 tt = atv.tv_sec; 199 if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt))) 200 return error; 201 202 retval[0] = tt; 203 return 0; 204 } 205 #endif 206 207 #if !defined(__aarch64__) 208 /* 209 * utime(). Do conversion to things that utimes() understands, 210 * and pass it on. 211 */ 212 int 213 linux_sys_utime(struct lwp *l, const struct linux_sys_utime_args *uap, register_t *retval) 214 { 215 /* { 216 syscallarg(const char *) path; 217 syscallarg(struct linux_utimbuf *)times; 218 } */ 219 int error; 220 struct timeval tv[2], *tvp; 221 struct linux_utimbuf lut; 222 223 if (SCARG(uap, times) != NULL) { 224 if ((error = copyin(SCARG(uap, times), &lut, sizeof lut))) 225 return error; 226 tv[0].tv_usec = tv[1].tv_usec = 0; 227 tv[0].tv_sec = lut.l_actime; 228 tv[1].tv_sec = lut.l_modtime; 229 tvp = tv; 230 } else 231 tvp = NULL; 232 233 return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW, 234 tvp, UIO_SYSSPACE); 235 } 236 #endif 237 238 #if !defined(__aarch64__) && !defined(__amd64__) 239 /* 240 * waitpid(2). Just forward on to linux_sys_wait4 with a NULL rusage. 241 */ 242 int 243 linux_sys_waitpid(struct lwp *l, const struct linux_sys_waitpid_args *uap, register_t *retval) 244 { 245 /* { 246 syscallarg(int) pid; 247 syscallarg(int *) status; 248 syscallarg(int) options; 249 } */ 250 struct linux_sys_wait4_args linux_w4a; 251 252 SCARG(&linux_w4a, pid) = SCARG(uap, pid); 253 SCARG(&linux_w4a, status) = SCARG(uap, status); 254 SCARG(&linux_w4a, options) = SCARG(uap, options); 255 SCARG(&linux_w4a, rusage) = NULL; 256 257 return linux_sys_wait4(l, &linux_w4a, retval); 258 } 259 #endif /* !aarch64 && !amd64 */ 260 261 int 262 linux_sys_setresgid(struct lwp *l, const struct linux_sys_setresgid_args *uap, register_t *retval) 263 { 264 /* { 265 syscallarg(gid_t) rgid; 266 syscallarg(gid_t) egid; 267 syscallarg(gid_t) sgid; 268 } */ 269 270 /* 271 * Note: These checks are a little different than the NetBSD 272 * setregid(2) call performs. This precisely follows the 273 * behavior of the Linux kernel. 274 */ 275 return do_setresgid(l, SCARG(uap,rgid), SCARG(uap, egid), 276 SCARG(uap, sgid), 277 ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S | 278 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 279 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S ); 280 } 281 282 int 283 linux_sys_getresgid(struct lwp *l, const struct linux_sys_getresgid_args *uap, register_t *retval) 284 { 285 /* { 286 syscallarg(gid_t *) rgid; 287 syscallarg(gid_t *) egid; 288 syscallarg(gid_t *) sgid; 289 } */ 290 kauth_cred_t pc = l->l_cred; 291 int error; 292 gid_t gid; 293 294 /* 295 * Linux copies these values out to userspace like so: 296 * 297 * 1. Copy out rgid. 298 * 2. If that succeeds, copy out egid. 299 * 3. If both of those succeed, copy out sgid. 300 */ 301 gid = kauth_cred_getgid(pc); 302 if ((error = copyout(&gid, SCARG(uap, rgid), sizeof(gid_t))) != 0) 303 return (error); 304 305 gid = kauth_cred_getegid(pc); 306 if ((error = copyout(&gid, SCARG(uap, egid), sizeof(gid_t))) != 0) 307 return (error); 308 309 gid = kauth_cred_getsvgid(pc); 310 311 return (copyout(&gid, SCARG(uap, sgid), sizeof(gid_t))); 312 } 313 314 #if !defined(__aarch64__) && !defined(__amd64__) 315 /* 316 * I wonder why Linux has settimeofday() _and_ stime().. Still, we 317 * need to deal with it. 318 */ 319 int 320 linux_sys_stime(struct lwp *l, const struct linux_sys_stime_args *uap, register_t *retval) 321 { 322 /* { 323 syscallarg(linux_time_t) *t; 324 } */ 325 struct timespec ats; 326 linux_time_t tt; 327 int error; 328 329 if ((error = copyin(SCARG(uap, t), &tt, sizeof tt)) != 0) 330 return error; 331 332 ats.tv_sec = tt; 333 ats.tv_nsec = 0; 334 335 if ((error = settime(l->l_proc, &ats))) 336 return (error); 337 338 return 0; 339 } 340 341 /* 342 * Implement the fs stat functions. Straightforward. 343 */ 344 int 345 linux_sys_statfs64(struct lwp *l, const struct linux_sys_statfs64_args *uap, register_t *retval) 346 { 347 /* { 348 syscallarg(const char *) path; 349 syscallarg(size_t) sz; 350 syscallarg(struct linux_statfs64 *) sp; 351 } */ 352 struct statvfs *sb; 353 struct linux_statfs64 ltmp; 354 int error; 355 356 if (SCARG(uap, sz) != sizeof ltmp) 357 return (EINVAL); 358 359 sb = STATVFSBUF_GET(); 360 error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb); 361 if (error == 0) { 362 bsd_to_linux_statfs64(sb, <mp); 363 error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 364 } 365 STATVFSBUF_PUT(sb); 366 return error; 367 } 368 369 int 370 linux_sys_fstatfs64(struct lwp *l, const struct linux_sys_fstatfs64_args *uap, register_t *retval) 371 { 372 /* { 373 syscallarg(int) fd; 374 syscallarg(size_t) sz; 375 syscallarg(struct linux_statfs64 *) sp; 376 } */ 377 struct statvfs *sb; 378 struct linux_statfs64 ltmp; 379 int error; 380 381 if (SCARG(uap, sz) != sizeof ltmp) 382 return (EINVAL); 383 384 sb = STATVFSBUF_GET(); 385 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb); 386 if (error == 0) { 387 bsd_to_linux_statfs64(sb, <mp); 388 error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 389 } 390 STATVFSBUF_PUT(sb); 391 return error; 392 } 393 #endif /* !aarch64 && !__amd64__ */ 394 #endif /* !COMPAT_LINUX32 */ 395