1 /* $NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2025 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __RCSID("$NetBSD: execregs.c,v 1.1 2025/02/27 00:55:32 riastradh Exp $"); 31 32 #include "execregs.h" 33 34 #include <errno.h> 35 #include <spawn.h> 36 #include <stddef.h> 37 #include <unistd.h> 38 39 extern char **environ; 40 41 static unsigned long 42 nonnull(unsigned long x) 43 { 44 45 x |= x << 8; 46 x |= x << 16; 47 return x; 48 } 49 50 int 51 execregschild(char *path) 52 { 53 register long edi __asm("edi") = nonnull('d'); 54 register long esi __asm("esi") = nonnull('s'); 55 /* ebp: frame pointer, can't touch that here, but it'll be nonnull */ 56 /* ebx: ps_strings, passed to child */ 57 register long edx __asm("edx") = nonnull('x'); 58 register long ecx __asm("ecx") = nonnull('c'); 59 register long eax __asm("eax") = nonnull('a'); 60 61 char *argv[] = {path, NULL}; 62 char **envp = environ; 63 64 /* 65 * Not perfect -- compiler might use some registers for 66 * stack/argument transfers, but all the arguments are nonnull 67 * so this is probably a good test anyway. 68 */ 69 __asm volatile("" : 70 "+r"(edi), 71 "+r"(esi), 72 "+r"(edx), 73 "+r"(ecx), 74 "+r"(eax) 75 :: "memory"); 76 77 return execve(path, argv, envp); 78 } 79 80 pid_t 81 spawnregschild(char *path, int fd) 82 { 83 register long edi __asm("edi") = nonnull('d'); 84 register long esi __asm("esi") = nonnull('s'); 85 /* ebp: frame pointer, can't touch that here, but it'll be nonnull */ 86 /* ebx: ps_strings, passed to child */ 87 register long edx __asm("edx") = nonnull('x'); 88 register long ecx __asm("ecx") = nonnull('c'); 89 register long eax __asm("eax") = nonnull('a'); 90 91 char *argv[] = {path, NULL}; 92 char **envp = environ; 93 posix_spawn_file_actions_t fileacts; 94 posix_spawnattr_t attr; 95 pid_t pid; 96 int error; 97 98 error = posix_spawn_file_actions_init(&fileacts); 99 if (error) 100 goto out; 101 error = posix_spawn_file_actions_adddup2(&fileacts, fd, STDOUT_FILENO); 102 if (error) 103 goto out; 104 error = posix_spawnattr_init(&attr); 105 if (error) 106 goto out; 107 108 /* 109 * Not perfect -- compiler might use some registers for 110 * stack/argument transfers, but all the arguments are nonnull 111 * so this is probably a good test anyway. 112 */ 113 __asm volatile("" : 114 "+r"(edi), 115 "+r"(esi), 116 "+r"(edx), 117 "+r"(ecx), 118 "+r"(eax) 119 :: "memory"); 120 121 error = posix_spawn(&pid, path, &fileacts, &attr, argv, envp); 122 if (error) 123 goto out; 124 125 out: posix_spawnattr_destroy(&attr); 126 posix_spawn_file_actions_destroy(&fileacts); 127 if (error) { 128 errno = error; 129 return -1; 130 } 131 return 0; 132 } 133