0001
0002
0003
0004
0005
0006
0007
0008 #define _GNU_SOURCE
0009 #include <sys/prctl.h>
0010 #include <sys/sysinfo.h>
0011 #include <sys/syscall.h>
0012 #include <signal.h>
0013
0014 #include <asm/unistd.h>
0015 #include "../kselftest_harness.h"
0016
0017 #ifndef PR_SET_SYSCALL_USER_DISPATCH
0018 # define PR_SET_SYSCALL_USER_DISPATCH 59
0019 # define PR_SYS_DISPATCH_OFF 0
0020 # define PR_SYS_DISPATCH_ON 1
0021 # define SYSCALL_DISPATCH_FILTER_ALLOW 0
0022 # define SYSCALL_DISPATCH_FILTER_BLOCK 1
0023 #endif
0024
0025 #ifndef SYS_USER_DISPATCH
0026 # define SYS_USER_DISPATCH 2
0027 #endif
0028
0029 #ifdef __NR_syscalls
0030 # define MAGIC_SYSCALL_1 (__NR_syscalls + 1)
0031 #else
0032 # define MAGIC_SYSCALL_1 (0xff00)
0033 #endif
0034
0035 #define SYSCALL_DISPATCH_ON(x) ((x) = SYSCALL_DISPATCH_FILTER_BLOCK)
0036 #define SYSCALL_DISPATCH_OFF(x) ((x) = SYSCALL_DISPATCH_FILTER_ALLOW)
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 TEST_SIGNAL(dispatch_trigger_sigsys, SIGSYS)
0060 {
0061 char sel = SYSCALL_DISPATCH_FILTER_ALLOW;
0062 struct sysinfo info;
0063 int ret;
0064
0065 ret = sysinfo(&info);
0066 ASSERT_EQ(0, ret);
0067
0068 ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, 0, &sel);
0069 ASSERT_EQ(0, ret) {
0070 TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
0071 }
0072
0073 SYSCALL_DISPATCH_ON(sel);
0074
0075 sysinfo(&info);
0076
0077 EXPECT_FALSE(true) {
0078 TH_LOG("Unreachable!");
0079 }
0080 }
0081
0082 TEST(bad_prctl_param)
0083 {
0084 char sel = SYSCALL_DISPATCH_FILTER_ALLOW;
0085 int op;
0086
0087
0088 op = -1;
0089 prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0, 0, &sel);
0090 ASSERT_EQ(EINVAL, errno);
0091
0092
0093 op = PR_SYS_DISPATCH_OFF;
0094
0095
0096 prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x1, 0x0, 0);
0097 EXPECT_EQ(EINVAL, errno);
0098
0099
0100 prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x0, 0xff, 0);
0101 EXPECT_EQ(EINVAL, errno);
0102
0103
0104 prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x0, 0x0, &sel);
0105 EXPECT_EQ(EINVAL, errno);
0106
0107
0108 errno = 0;
0109 prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x0, 0x0, 0x0);
0110 EXPECT_EQ(0, errno);
0111
0112
0113 op = PR_SYS_DISPATCH_ON;
0114
0115
0116 prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x1, 0x0, &sel);
0117 EXPECT_EQ(EINVAL, errno);
0118 prctl(PR_SET_SYSCALL_USER_DISPATCH, op, -1L, 0x0, &sel);
0119 EXPECT_EQ(EINVAL, errno);
0120
0121
0122 prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x0, 0x1, (void *) -1);
0123 ASSERT_EQ(EFAULT, errno);
0124
0125
0126
0127
0128 prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 1, -1L, &sel);
0129 ASSERT_EQ(EINVAL, errno) {
0130 TH_LOG("Should reject bad syscall range");
0131 }
0132
0133
0134
0135
0136 prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, -1L, 0x1, &sel);
0137 ASSERT_EQ(EINVAL, errno) {
0138 TH_LOG("Should reject bad syscall range");
0139 }
0140 }
0141
0142
0143
0144
0145
0146 char glob_sel;
0147 int nr_syscalls_emulated;
0148 int si_code;
0149 int si_errno;
0150
0151 static void handle_sigsys(int sig, siginfo_t *info, void *ucontext)
0152 {
0153 si_code = info->si_code;
0154 si_errno = info->si_errno;
0155
0156 if (info->si_syscall == MAGIC_SYSCALL_1)
0157 nr_syscalls_emulated++;
0158
0159
0160 SYSCALL_DISPATCH_OFF(glob_sel);
0161 }
0162
0163 TEST(dispatch_and_return)
0164 {
0165 long ret;
0166 struct sigaction act;
0167 sigset_t mask;
0168
0169 glob_sel = 0;
0170 nr_syscalls_emulated = 0;
0171 si_code = 0;
0172 si_errno = 0;
0173
0174 memset(&act, 0, sizeof(act));
0175 sigemptyset(&mask);
0176
0177 act.sa_sigaction = handle_sigsys;
0178 act.sa_flags = SA_SIGINFO;
0179 act.sa_mask = mask;
0180
0181 ret = sigaction(SIGSYS, &act, NULL);
0182 ASSERT_EQ(0, ret);
0183
0184
0185 SYSCALL_DISPATCH_OFF(glob_sel);
0186
0187 ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, 0, &glob_sel);
0188 ASSERT_EQ(0, ret) {
0189 TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
0190 }
0191
0192
0193 SYSCALL_DISPATCH_OFF(glob_sel);
0194 ret = syscall(MAGIC_SYSCALL_1);
0195 EXPECT_EQ(-1, ret) {
0196 TH_LOG("Dispatch triggered unexpectedly");
0197 }
0198
0199
0200 nr_syscalls_emulated = 0;
0201 SYSCALL_DISPATCH_ON(glob_sel);
0202
0203 ret = syscall(MAGIC_SYSCALL_1);
0204 EXPECT_EQ(MAGIC_SYSCALL_1, ret) {
0205 TH_LOG("Failed to intercept syscall");
0206 }
0207 EXPECT_EQ(1, nr_syscalls_emulated) {
0208 TH_LOG("Failed to emulate syscall");
0209 }
0210 ASSERT_EQ(SYS_USER_DISPATCH, si_code) {
0211 TH_LOG("Bad si_code in SIGSYS");
0212 }
0213 ASSERT_EQ(0, si_errno) {
0214 TH_LOG("Bad si_errno in SIGSYS");
0215 }
0216 }
0217
0218 TEST_SIGNAL(bad_selector, SIGSYS)
0219 {
0220 long ret;
0221 struct sigaction act;
0222 sigset_t mask;
0223 struct sysinfo info;
0224
0225 glob_sel = SYSCALL_DISPATCH_FILTER_ALLOW;
0226 nr_syscalls_emulated = 0;
0227 si_code = 0;
0228 si_errno = 0;
0229
0230 memset(&act, 0, sizeof(act));
0231 sigemptyset(&mask);
0232
0233 act.sa_sigaction = handle_sigsys;
0234 act.sa_flags = SA_SIGINFO;
0235 act.sa_mask = mask;
0236
0237 ret = sigaction(SIGSYS, &act, NULL);
0238 ASSERT_EQ(0, ret);
0239
0240
0241 SYSCALL_DISPATCH_OFF(glob_sel);
0242
0243 ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, 0, &glob_sel);
0244 ASSERT_EQ(0, ret) {
0245 TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
0246 }
0247
0248 glob_sel = -1;
0249
0250 sysinfo(&info);
0251
0252
0253
0254
0255
0256 EXPECT_FALSE(true) {
0257 TH_LOG("Unreachable!");
0258 }
0259 }
0260
0261 TEST(disable_dispatch)
0262 {
0263 int ret;
0264 struct sysinfo info;
0265 char sel = 0;
0266
0267 ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, 0, &sel);
0268 ASSERT_EQ(0, ret) {
0269 TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
0270 }
0271
0272
0273 SYSCALL_DISPATCH_OFF(glob_sel);
0274
0275 ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_OFF, 0, 0, 0);
0276 EXPECT_EQ(0, ret) {
0277 TH_LOG("Failed to unset syscall user dispatch");
0278 }
0279
0280
0281 SYSCALL_DISPATCH_ON(glob_sel);
0282
0283 ret = syscall(__NR_sysinfo, &info);
0284 EXPECT_EQ(0, ret) {
0285 TH_LOG("Dispatch triggered unexpectedly");
0286 }
0287 }
0288
0289 TEST(direct_dispatch_range)
0290 {
0291 int ret = 0;
0292 struct sysinfo info;
0293 char sel = SYSCALL_DISPATCH_FILTER_ALLOW;
0294
0295
0296
0297
0298
0299 ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, -1L, &sel);
0300 ASSERT_EQ(0, ret) {
0301 TH_LOG("Kernel does not support CONFIG_SYSCALL_USER_DISPATCH");
0302 }
0303
0304 SYSCALL_DISPATCH_ON(sel);
0305
0306 ret = sysinfo(&info);
0307 ASSERT_EQ(0, ret) {
0308 TH_LOG("Dispatch triggered unexpectedly");
0309 }
0310 }
0311
0312 TEST_HARNESS_MAIN