aboutsummaryrefslogtreecommitdiffstats
path: root/ports/linux/pseudo_wrappers.c
blob: ed3411554255a6de1569156ba6e2abbb714b2480 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * SPDX-License-Identifier: LGPL-2.1-only
 *
 */
/* the unix port wants to know that real_stat() and
 * friends exist.  So they do. And because the Linux
 * port really uses stat64 for those...
 */
int
pseudo_stat(const char *path, struct stat *buf) {
	return real___xstat(_STAT_VER, path, buf);
}

int
pseudo_lstat(const char *path, struct stat *buf) {
	return real___lxstat(_STAT_VER, path, buf);
}

int
pseudo_fstat(int fd, struct stat *buf) {
	return real___fxstat(_STAT_VER, fd, buf);
}

int
pseudo_stat64(const char *path, struct stat64 *buf) {
	return real___xstat64(_STAT_VER, path, buf);
}

int
pseudo_lstat64(const char *path, struct stat64 *buf) {
	return real___lxstat64(_STAT_VER, path, buf);
}

int
pseudo_fstat64(int fd, struct stat64 *buf) {
	return real___fxstat64(_STAT_VER, fd, buf);
}

/* similar thing happens with mknod */
int
pseudo_mknod(const char *path, mode_t mode, dev_t dev) {
	return real___xmknod(_MKNOD_VER, path, mode, &dev);
}

int
pseudo_mknodat(int dirfd, const char *path, mode_t mode, dev_t dev) {
	return real___xmknodat(_MKNOD_VER, dirfd, path, mode, &dev);
}

int pseudo_capset(cap_user_header_t hdrp, const cap_user_data_t datap) {
	(void)hdrp;
	(void)datap;

	return 0;
}

long
syscall(long number, ...) {
	long rc = -1;
	va_list ap;

	if (!pseudo_check_wrappers() || !real_syscall) {
		/* rc was initialized to the "failure" value */
		pseudo_enosys("syscall");
		return rc;
	}

#ifdef SYS_renameat2
	/* concerns exist about trying to parse arguments because syscall(2)
	 * specifies strange ABI behaviors. If we can get better clarity on
	 * that, it could make sense to redirect to wrap_renameat2().
	 */
	if (number == SYS_renameat2) {
		errno = ENOSYS;
		return -1;
	}
#else
	(void) number;
#endif

#ifdef SYS_seccomp
	/* pseudo and seccomp are incompatible as pseudo uses different syscalls
	 * so pretend to enable seccomp but really do nothing */
	if (number == SYS_seccomp) {
		unsigned long cmd;
		va_start(ap, number);
		cmd = va_arg(ap, unsigned long);
		va_end(ap);
		if (cmd == SECCOMP_SET_MODE_FILTER) {
		    return 0;
		}
	}
#endif

	/* gcc magic to attempt to just pass these args to syscall. we have to
	 * guess about the number of args; the docs discuss calling conventions
	 * up to 7, so let's try that?
	 */
	void *res = __builtin_apply((void (*)()) real_syscall, __builtin_apply_args(), sizeof(long) * 7);
	__builtin_return(res);
}

/* unused.
 */
static long wrap_syscall(long nr, va_list ap) {
	(void) nr;
	(void) ap;
	return -1;
}

int
prctl(int option, ...) {
	int rc = -1;
	va_list ap;

	if (!pseudo_check_wrappers() || !real_prctl) {
		/* rc was initialized to the "failure" value */
		pseudo_enosys("prctl");
		return rc;
	}

#ifdef SECCOMP_SET_MODE_FILTER
	/* pseudo and seccomp are incompatible as pseudo uses different syscalls
	 * so pretend to enable seccomp but really do nothing */
	if (option == PR_SET_SECCOMP) {
		unsigned long cmd;
		va_start(ap, option);
		cmd = va_arg(ap, unsigned long);
		va_end(ap);
		if (cmd == SECCOMP_SET_MODE_FILTER) {
		    return 0;
		}
	}
#endif

	/* gcc magic to attempt to just pass these args to prctl. we have to
	 * guess about the number of args; the docs discuss calling conventions
	 * up to 5, so let's try that?
	 */
	void *res = __builtin_apply((void (*)()) real_prctl, __builtin_apply_args(), sizeof(long) * 5);
	__builtin_return(res);
}

/* unused.
 */
static int wrap_prctl(int option, va_list ap) {
	(void) option;
	(void) ap;
	return -1;
}