1 /* $NetBSD: linux_misc_notalpha.c,v 1.116 2026/09/20 13:43:51 riastradh 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.116 2026/09/20 13:43:51 riastradh 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 architecture 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 /* 89 * Alarm. This is a libc call which uses setitimer(2) in NetBSD. 90 * Do the same here. 91 */ 92 int 93 linux_sys_alarm(struct lwp *l, const struct linux_sys_alarm_args *uap, register_t *retval) 94 { 95 /* { 96 syscallarg(unsigned int) secs; 97 } */ 98 struct proc *p = l->l_proc; 99 struct itimerval itv, oitv; 100 int error; 101 102 timerclear(&itv.it_interval); 103 itv.it_value.tv_sec = SCARG(uap, secs); 104 itv.it_value.tv_usec = 0; 105 if (itv.it_value.tv_sec < 0) { 106 return EINVAL; 107 } 108 109 if ((error = dogetitimer(p, ITIMER_REAL, &oitv)) != 0) { 110 return error; 111 } 112 if (oitv.it_value.tv_usec) { 113 oitv.it_value.tv_sec++; 114 } 115 116 if ((error = dosetitimer(p, ITIMER_REAL, &itv)) != 0) { 117 return error; 118 } 119 120 *retval = oitv.it_value.tv_sec; 121 return 0; 122 } 123 #endif /* !COMPAT_LINUX32 */ 124 125 #if !defined(__aarch64__) && !defined(__amd64__) 126 int 127 linux_sys_nice(struct lwp *l, const struct linux_sys_nice_args *uap, register_t *retval) 128 { 129 /* { 130 syscallarg(int) incr; 131 } */ 132 struct proc *p = l->l_proc; 133 struct sys_setpriority_args bsa; 134 int error; 135 136 memset(&bsa, 0, sizeof(bsa)); 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 /* !__aarch64__ && !__amd64__ */ 145 146 #ifndef COMPAT_LINUX32 147 #if !defined(__aarch64__) && !defined(__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 memset(&da, 0, sizeof(da)); 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 memset(&linux_w4a, 0, sizeof(linux_w4a)); 253 SCARG(&linux_w4a, pid) = SCARG(uap, pid); 254 SCARG(&linux_w4a, status) = SCARG(uap, status); 255 SCARG(&linux_w4a, options) = SCARG(uap, options); 256 SCARG(&linux_w4a, rusage) = NULL; 257 258 return linux_sys_wait4(l, &linux_w4a, retval); 259 } 260 #endif /* !aarch64 && !amd64 */ 261 262 int 263 linux_sys_setresgid(struct lwp *l, const struct linux_sys_setresgid_args *uap, register_t *retval) 264 { 265 /* { 266 syscallarg(gid_t) rgid; 267 syscallarg(gid_t) egid; 268 syscallarg(gid_t) sgid; 269 } */ 270 271 /* 272 * Note: These checks are a little different than the NetBSD 273 * setregid(2) call performs. This precisely follows the 274 * behavior of the Linux kernel. 275 */ 276 return do_setresgid(l, SCARG(uap,rgid), SCARG(uap, egid), 277 SCARG(uap, sgid), 278 ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S | 279 ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S | 280 ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S ); 281 } 282 283 int 284 linux_sys_getresgid(struct lwp *l, const struct linux_sys_getresgid_args *uap, register_t *retval) 285 { 286 /* { 287 syscallarg(gid_t *) rgid; 288 syscallarg(gid_t *) egid; 289 syscallarg(gid_t *) sgid; 290 } */ 291 kauth_cred_t pc = l->l_cred; 292 int error; 293 gid_t gid; 294 295 /* 296 * Linux copies these values out to userspace like so: 297 * 298 * 1. Copy out rgid. 299 * 2. If that succeeds, copy out egid. 300 * 3. If both of those succeed, copy out sgid. 301 */ 302 gid = kauth_cred_getgid(pc); 303 if ((error = copyout(&gid, SCARG(uap, rgid), sizeof(gid_t))) != 0) 304 return (error); 305 306 gid = kauth_cred_getegid(pc); 307 if ((error = copyout(&gid, SCARG(uap, egid), sizeof(gid_t))) != 0) 308 return (error); 309 310 gid = kauth_cred_getsvgid(pc); 311 312 return (copyout(&gid, SCARG(uap, sgid), sizeof(gid_t))); 313 } 314 315 #if !defined(__aarch64__) && !defined(__amd64__) 316 /* 317 * I wonder why Linux has settimeofday() _and_ stime().. Still, we 318 * need to deal with it. 319 */ 320 int 321 linux_sys_stime(struct lwp *l, const struct linux_sys_stime_args *uap, register_t *retval) 322 { 323 /* { 324 syscallarg(linux_time_t) *t; 325 } */ 326 struct timespec ats; 327 linux_time_t tt; 328 int error; 329 330 if ((error = copyin(SCARG(uap, t), &tt, sizeof tt)) != 0) 331 return error; 332 333 ats.tv_sec = tt; 334 ats.tv_nsec = 0; 335 336 if ((error = settime(l->l_proc, &ats))) 337 return (error); 338 339 return 0; 340 } 341 342 /* 343 * Implement the fs stat functions. Straightforward. 344 */ 345 int 346 linux_sys_statfs64(struct lwp *l, const struct linux_sys_statfs64_args *uap, register_t *retval) 347 { 348 /* { 349 syscallarg(const char *) path; 350 syscallarg(size_t) sz; 351 syscallarg(struct linux_statfs64 *) sp; 352 } */ 353 struct statvfs *sb; 354 struct linux_statfs64 ltmp; 355 int error; 356 357 if (SCARG(uap, sz) != sizeof ltmp) 358 return (EINVAL); 359 360 sb = STATVFSBUF_GET(); 361 error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb); 362 if (error == 0) { 363 bsd_to_linux_statfs64(sb, <mp); 364 error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 365 } 366 STATVFSBUF_PUT(sb); 367 return error; 368 } 369 370 int 371 linux_sys_fstatfs64(struct lwp *l, const struct linux_sys_fstatfs64_args *uap, register_t *retval) 372 { 373 /* { 374 syscallarg(int) fd; 375 syscallarg(size_t) sz; 376 syscallarg(struct linux_statfs64 *) sp; 377 } */ 378 struct statvfs *sb; 379 struct linux_statfs64 ltmp; 380 int error; 381 382 if (SCARG(uap, sz) != sizeof ltmp) 383 return (EINVAL); 384 385 sb = STATVFSBUF_GET(); 386 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb); 387 if (error == 0) { 388 bsd_to_linux_statfs64(sb, <mp); 389 error = copyout(<mp, SCARG(uap, sp), sizeof ltmp); 390 } 391 STATVFSBUF_PUT(sb); 392 return error; 393 } 394 #endif /* !aarch64 && !__amd64__ */ 395 #endif /* !COMPAT_LINUX32 */ 396