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