1 /* 2 * process related system call shims and definitions 3 * 4 * Copyright (c) 2013-2014 Stacey D. Son 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef BSD_PROC_H_ 21 #define BSD_PROC_H_ 22 23 #include <sys/resource.h> 24 25 #include "qemu-bsd.h" 26 #include "gdbstub/syscalls.h" 27 #include "qemu/plugin.h" 28 29 extern int _getlogin(char*, int); 30 int bsd_get_ncpu(void); 31 32 /* exit(2) */ 33 static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1) 34 { 35 #ifdef TARGET_GPROF 36 _mcleanup(); 37 #endif 38 gdb_exit(arg1); 39 qemu_plugin_user_exit(); 40 _exit(arg1); 41 42 return 0; 43 } 44 45 /* getgroups(2) */ 46 static inline abi_long do_bsd_getgroups(abi_long gidsetsize, abi_long arg2) 47 { 48 abi_long ret; 49 uint32_t *target_grouplist; 50 g_autofree gid_t *grouplist; 51 int i; 52 53 grouplist = g_try_new(gid_t, gidsetsize); 54 ret = get_errno(getgroups(gidsetsize, grouplist)); 55 if (gidsetsize != 0) { 56 if (!is_error(ret)) { 57 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0); 58 if (!target_grouplist) { 59 return -TARGET_EFAULT; 60 } 61 for (i = 0; i < ret; i++) { 62 target_grouplist[i] = tswap32(grouplist[i]); 63 } 64 unlock_user(target_grouplist, arg2, gidsetsize * 2); 65 } 66 } 67 return ret; 68 } 69 70 /* setgroups(2) */ 71 static inline abi_long do_bsd_setgroups(abi_long gidsetsize, abi_long arg2) 72 { 73 uint32_t *target_grouplist; 74 g_autofree gid_t *grouplist; 75 int i; 76 77 grouplist = g_try_new(gid_t, gidsetsize); 78 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1); 79 if (!target_grouplist) { 80 return -TARGET_EFAULT; 81 } 82 for (i = 0; i < gidsetsize; i++) { 83 grouplist[i] = tswap32(target_grouplist[i]); 84 } 85 unlock_user(target_grouplist, arg2, 0); 86 return get_errno(setgroups(gidsetsize, grouplist)); 87 } 88 89 /* umask(2) */ 90 static inline abi_long do_bsd_umask(abi_long arg1) 91 { 92 return get_errno(umask(arg1)); 93 } 94 95 /* setlogin(2) */ 96 static inline abi_long do_bsd_setlogin(abi_long arg1) 97 { 98 abi_long ret; 99 void *p; 100 101 p = lock_user_string(arg1); 102 if (p == NULL) { 103 return -TARGET_EFAULT; 104 } 105 ret = get_errno(setlogin(p)); 106 unlock_user(p, arg1, 0); 107 108 return ret; 109 } 110 111 /* getlogin(2) */ 112 static inline abi_long do_bsd_getlogin(abi_long arg1, abi_long arg2) 113 { 114 abi_long ret; 115 void *p; 116 117 p = lock_user(VERIFY_WRITE, arg1, arg2, 0); 118 if (p == NULL) { 119 return -TARGET_EFAULT; 120 } 121 ret = get_errno(_getlogin(p, arg2)); 122 unlock_user(p, arg1, arg2); 123 124 return ret; 125 } 126 127 /* getrusage(2) */ 128 static inline abi_long do_bsd_getrusage(abi_long who, abi_ulong target_addr) 129 { 130 abi_long ret; 131 struct rusage rusage; 132 133 ret = get_errno(getrusage(who, &rusage)); 134 if (!is_error(ret)) { 135 host_to_target_rusage(target_addr, &rusage); 136 } 137 return ret; 138 } 139 140 /* getrlimit(2) */ 141 static inline abi_long do_bsd_getrlimit(abi_long arg1, abi_ulong arg2) 142 { 143 abi_long ret; 144 int resource = target_to_host_resource(arg1); 145 struct target_rlimit *target_rlim; 146 struct rlimit rlim; 147 148 switch (resource) { 149 case RLIMIT_STACK: 150 rlim.rlim_cur = target_dflssiz; 151 rlim.rlim_max = target_maxssiz; 152 ret = 0; 153 break; 154 155 case RLIMIT_DATA: 156 rlim.rlim_cur = target_dfldsiz; 157 rlim.rlim_max = target_maxdsiz; 158 ret = 0; 159 break; 160 161 default: 162 ret = get_errno(getrlimit(resource, &rlim)); 163 break; 164 } 165 if (!is_error(ret)) { 166 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) { 167 return -TARGET_EFAULT; 168 } 169 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur); 170 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max); 171 unlock_user_struct(target_rlim, arg2, 1); 172 } 173 return ret; 174 } 175 176 /* setrlimit(2) */ 177 static inline abi_long do_bsd_setrlimit(abi_long arg1, abi_ulong arg2) 178 { 179 abi_long ret; 180 int resource = target_to_host_resource(arg1); 181 struct target_rlimit *target_rlim; 182 struct rlimit rlim; 183 184 if (RLIMIT_STACK == resource) { 185 /* XXX We should, maybe, allow the stack size to shrink */ 186 ret = -TARGET_EPERM; 187 } else { 188 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) { 189 return -TARGET_EFAULT; 190 } 191 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur); 192 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max); 193 unlock_user_struct(target_rlim, arg2, 0); 194 ret = get_errno(setrlimit(resource, &rlim)); 195 } 196 return ret; 197 } 198 199 /* getpid(2) */ 200 static inline abi_long do_bsd_getpid(void) 201 { 202 return get_errno(getpid()); 203 } 204 205 /* getppid(2) */ 206 static inline abi_long do_bsd_getppid(void) 207 { 208 return get_errno(getppid()); 209 } 210 211 /* getuid(2) */ 212 static inline abi_long do_bsd_getuid(void) 213 { 214 return get_errno(getuid()); 215 } 216 217 /* geteuid(2) */ 218 static inline abi_long do_bsd_geteuid(void) 219 { 220 return get_errno(geteuid()); 221 } 222 223 /* getgid(2) */ 224 static inline abi_long do_bsd_getgid(void) 225 { 226 return get_errno(getgid()); 227 } 228 229 /* getegid(2) */ 230 static inline abi_long do_bsd_getegid(void) 231 { 232 return get_errno(getegid()); 233 } 234 235 /* setuid(2) */ 236 static inline abi_long do_bsd_setuid(abi_long arg1) 237 { 238 return get_errno(setuid(arg1)); 239 } 240 241 /* seteuid(2) */ 242 static inline abi_long do_bsd_seteuid(abi_long arg1) 243 { 244 return get_errno(seteuid(arg1)); 245 } 246 247 /* setgid(2) */ 248 static inline abi_long do_bsd_setgid(abi_long arg1) 249 { 250 return get_errno(setgid(arg1)); 251 } 252 253 /* setegid(2) */ 254 static inline abi_long do_bsd_setegid(abi_long arg1) 255 { 256 return get_errno(setegid(arg1)); 257 } 258 259 /* getpgid(2) */ 260 static inline abi_long do_bsd_getpgid(pid_t pid) 261 { 262 return get_errno(getpgid(pid)); 263 } 264 265 /* setpgid(2) */ 266 static inline abi_long do_bsd_setpgid(int pid, int pgrp) 267 { 268 return get_errno(setpgid(pid, pgrp)); 269 } 270 271 /* getpgrp(2) */ 272 static inline abi_long do_bsd_getpgrp(void) 273 { 274 return get_errno(getpgrp()); 275 } 276 277 /* setreuid(2) */ 278 static inline abi_long do_bsd_setreuid(abi_long arg1, abi_long arg2) 279 { 280 return get_errno(setreuid(arg1, arg2)); 281 } 282 283 /* setregid(2) */ 284 static inline abi_long do_bsd_setregid(abi_long arg1, abi_long arg2) 285 { 286 return get_errno(setregid(arg1, arg2)); 287 } 288 289 /* setresgid(2) */ 290 static inline abi_long do_bsd_setresgid(gid_t rgid, gid_t egid, gid_t sgid) 291 { 292 return get_errno(setresgid(rgid, egid, sgid)); 293 } 294 295 /* setresuid(2) */ 296 static inline abi_long do_bsd_setresuid(uid_t ruid, uid_t euid, uid_t suid) 297 { 298 return get_errno(setresuid(ruid, euid, suid)); 299 } 300 301 /* getresuid(2) */ 302 static inline abi_long do_bsd_getresuid(abi_ulong arg1, abi_ulong arg2, 303 abi_ulong arg3) 304 { 305 abi_long ret; 306 uid_t ruid, euid, suid; 307 308 ret = get_errno(getresuid(&ruid, &euid, &suid)); 309 if (is_error(ret)) { 310 return ret; 311 } 312 if (put_user_s32(ruid, arg1)) { 313 return -TARGET_EFAULT; 314 } 315 if (put_user_s32(euid, arg2)) { 316 return -TARGET_EFAULT; 317 } 318 if (put_user_s32(suid, arg3)) { 319 return -TARGET_EFAULT; 320 } 321 return ret; 322 } 323 324 /* getresgid(2) */ 325 static inline abi_long do_bsd_getresgid(abi_ulong arg1, abi_ulong arg2, 326 abi_ulong arg3) 327 { 328 abi_long ret; 329 uid_t ruid, euid, suid; 330 331 ret = get_errno(getresgid(&ruid, &euid, &suid)); 332 if (is_error(ret)) { 333 return ret; 334 } 335 if (put_user_s32(ruid, arg1)) { 336 return -TARGET_EFAULT; 337 } 338 if (put_user_s32(euid, arg2)) { 339 return -TARGET_EFAULT; 340 } 341 if (put_user_s32(suid, arg3)) { 342 return -TARGET_EFAULT; 343 } 344 return ret; 345 } 346 347 /* getsid(2) */ 348 static inline abi_long do_bsd_getsid(abi_long arg1) 349 { 350 return get_errno(getsid(arg1)); 351 } 352 353 /* setsid(2) */ 354 static inline abi_long do_bsd_setsid(void) 355 { 356 return get_errno(setsid()); 357 } 358 359 /* issetugid(2) */ 360 static inline abi_long do_bsd_issetugid(void) 361 { 362 return get_errno(issetugid()); 363 } 364 365 #endif /* !BSD_PROC_H_ */ 366