]>
git.proxmox.com Git - mirror_lxcfs.git/blob - tests/test_syscalls.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
17 #include <sys/mount.h>
18 #include <sys/socket.h>
20 #include <sys/sysmacros.h>
21 #include <sys/types.h>
22 #include <sys/types.h>
24 #include <sys/xattr.h>
28 void test_open(const char *path
)
30 int fd
= open(path
, O_RDONLY
);
32 fprintf(stderr
, "leak at open of %s\n", path
);
35 if (errno
!= ENOENT
) {
36 fprintf(stderr
, "leak at open of %s: errno was %d\n", path
, errno
);
41 void test_stat(const char *path
)
44 if (stat(path
, &sb
) >= 0) {
45 fprintf(stderr
, "leak at stat of %s\n", path
);
48 if (errno
!= ENOENT
) {
49 fprintf(stderr
, "leak at stat of %s: errno was %d\n", path
, errno
);
54 void test_access(const char *path
)
56 if (access(path
, O_RDONLY
) >= 0) {
57 fprintf(stderr
, "leak at access of %s\n", path
);
60 if (errno
!= ENOENT
) {
61 fprintf(stderr
, "leak at access of %s: errno was %d\n", path
, errno
);
66 void test_bind(const char *path
)
69 struct sockaddr_un my_addr
;
71 sfd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
74 fprintf(stderr
, "Failed to open a socket for bind test\n");
77 memset(&my_addr
, 0, sizeof(struct sockaddr_un
));
78 my_addr
.sun_family
= AF_UNIX
;
79 strncpy(my_addr
.sun_path
, path
,
80 sizeof(my_addr
.sun_path
) - 1);
81 if (bind(sfd
, (struct sockaddr
*) &my_addr
,
82 sizeof(struct sockaddr_un
)) != -1) {
83 fprintf(stderr
, "leak at bind of %s\n", path
);
86 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
87 fprintf(stderr
, "leak at bind of %s: errno was %s\n", path
, strerror(errno
));
93 void test_bindmount(const char *path
)
95 if (mount(path
, path
, "none", MS_BIND
, NULL
) == 0) {
96 fprintf(stderr
, "leak at bind mount of %s\n", path
);
101 void test_truncate(const char *path
)
103 if (truncate(path
, 0) == 0) {
104 fprintf(stderr
, "leak at truncate of %s\n", path
);
109 void test_chdir(const char *path
)
111 if (chdir(path
) == 0) {
112 fprintf(stderr
, "leak at chdir to %s\n", path
);
117 void test_rename(const char *path
)
119 char *d
= strdupa(path
), *tmpname
;
121 size_t len
= strlen(path
) + 30;
123 tmpname
= alloca(len
);
124 snprintf(tmpname
, len
, "%s/%d", d
, (int)getpid());
125 if (rename(path
, tmpname
) == 0 || errno
!= ENOENT
) {
126 fprintf(stderr
, "leak at rename of %s\n", path
);
131 void test_mkdir(const char *path
)
133 size_t len
= strlen(path
) + 30;
134 char *tmpname
= alloca(len
);
135 snprintf(tmpname
, len
, "%s/%d", path
, (int)getpid());
137 if (mkdir(path
, 0755) == 0) {
138 fprintf(stderr
, "leak at mkdir of %s\n", path
);
141 if (errno
!= ENOENT
) {
142 fprintf(stderr
, "leak at mkdir of %s, errno was %s\n", path
, strerror(errno
));
145 if (mkdir(tmpname
, 0755) == 0) {
146 fprintf(stderr
, "leak at mkdir of %s\n", tmpname
);
149 if (errno
!= ENOENT
) {
150 fprintf(stderr
, "leak at mkdir of %s, errno was %s\n", path
, strerror(errno
));
155 void test_rmdir(const char *path
)
157 size_t len
= strlen(path
) + 30;
158 char *tmpname
= alloca(len
);
159 snprintf(tmpname
, len
, "%s/%d", path
, (int)getpid());
161 if (rmdir(path
) == 0 || errno
!= ENOENT
) {
162 fprintf(stderr
, "leak at rmdir of %s\n", path
);
165 if (rmdir(tmpname
) == 0 || errno
!= ENOENT
) {
166 fprintf(stderr
, "leak at rmdir of %s\n", tmpname
);
171 void test_creat(const char *path
)
173 if (creat(path
, 0755) >= 0) {
174 fprintf(stderr
, "leak at creat of %s\n", path
);
177 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
178 fprintf(stderr
, "leak at creat of %s: errno was %s\n", path
, strerror(errno
));
183 void test_link(const char *path
)
185 char *d
= strdupa(path
), *tmpname
;
187 size_t len
= strlen(path
) + 30;
188 tmpname
= alloca(len
);
189 snprintf(tmpname
, len
, "%s/%d", d
, (int)getpid());
191 if (link(path
, tmpname
) == 0) {
192 fprintf(stderr
, "leak at link of %s\n", path
);
195 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
196 fprintf(stderr
, "leak at link of %s: errno was %s\n", path
, strerror(errno
));
200 if (link(tmpname
, path
) == 0) {
201 fprintf(stderr
, "leak at link (2) of %s\n", path
);
204 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
205 fprintf(stderr
, "leak at link (2) of %s: errno was %s\n", path
, strerror(errno
));
210 void test_unlink(const char *path
)
212 if (unlink(path
) == 0) {
213 fprintf(stderr
, "leak at unlink of %s\n", path
);
216 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
217 fprintf(stderr
, "leak at unlink of %s: errno was %s\n", path
, strerror(errno
));
222 void test_symlink(const char *path
)
224 char *d
= strdupa(path
), *tmpname
;
226 size_t len
= strlen(path
) + 30;
227 tmpname
= alloca(len
);
228 snprintf(tmpname
, len
, "%s/%d", d
, (int)getpid());
230 if (symlink(tmpname
, path
) == 0) {
231 fprintf(stderr
, "leak at symlink of %s\n", path
);
234 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
235 fprintf(stderr
, "leak at symlink of %s: errno was %s\n", path
, strerror(errno
));
238 if (symlink(path
, tmpname
) == 0) {
239 fprintf(stderr
, "leak at symlink (2) of %s\n", path
);
242 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
243 fprintf(stderr
, "leak at symlink (2) of %s: errno was %s\n", path
, strerror(errno
));
248 void test_readlink(const char *path
)
250 char *dest
= alloca(2 * strlen(path
));
252 if (readlink(path
, dest
, 2 * strlen(path
)) >= 0) {
253 fprintf(stderr
, "leak at readlink of %s\n", path
);
256 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
257 fprintf(stderr
, "leak at readlink of %s: errno was %s\n", path
, strerror(errno
));
262 void test_chmod(const char *path
)
264 if (chmod(path
, 0755) == 0) {
265 fprintf(stderr
, "leak at chmod of %s\n", path
);
268 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
269 fprintf(stderr
, "leak at chmod of %s: errno was %s\n", path
, strerror(errno
));
274 void test_chown(const char *path
)
276 if (chown(path
, 0, 0) == 0) {
277 fprintf(stderr
, "leak at chown of %s\n", path
);
280 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
281 fprintf(stderr
, "leak at chown of %s: errno was %s\n", path
, strerror(errno
));
286 void test_lchown(const char *path
)
288 if (lchown(path
, 0, 0) == 0) {
289 fprintf(stderr
, "leak at lchown of %s\n", path
);
292 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
293 fprintf(stderr
, "leak at lchown of %s: errno was %s\n", path
, strerror(errno
));
298 void test_mknod(const char *path
)
300 if (mknod(path
, 0755, makedev(0, 0)) == 0) {
301 fprintf(stderr
, "leak at mknod of %s\n", path
);
304 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
305 fprintf(stderr
, "leak at mknod of %s: errno was %s\n", path
, strerror(errno
));
310 void test_chroot(const char *path
)
312 if (chroot(path
) == 0) {
313 fprintf(stderr
, "leak at chroot of %s\n", path
);
316 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
317 fprintf(stderr
, "leak at chroot of %s: errno was %s\n", path
, strerror(errno
));
322 void test_xattrs(const char *path
)
325 * might consider doing all of:
336 if (getxattr(path
, "security.selinux", value
, 200) >= 0) {
337 fprintf(stderr
, "leak at getxattr of %s\n", path
);
340 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
341 fprintf(stderr
, "leak at getxattr of %s: errno was %s\n", path
, strerror(errno
));
346 void test_utimes(const char *path
)
348 struct utimbuf times
;
352 if (utime(path
, ×
) == 0) {
353 fprintf(stderr
, "leak at utime of %s\n", path
);
356 if (errno
!= ENOENT
&& errno
!= ENOSYS
) {
357 fprintf(stderr
, "leak at utime of %s: errno was %s\n", path
, strerror(errno
));
362 void test_openat(const char *path
)
364 char *d
= strdupa(path
), *f
, *tmpname
;
368 fd
= open(d
, O_RDONLY
);
370 fprintf(stderr
, "Error in openat test: could not open parent dir\n");
371 fprintf(stderr
, "(this is expected on the second run)\n");
374 fd2
= openat(fd
, f
, O_RDONLY
);
375 if (fd2
>= 0 || errno
!= ENOENT
) {
376 fprintf(stderr
, "leak at openat of %s\n", f
);
379 size_t len
= strlen(path
) + strlen("/cgroup.procs") + 1;
380 tmpname
= alloca(len
);
381 snprintf(tmpname
, len
, "%s/cgroup.procs", f
);
382 fd2
= openat(fd
, tmpname
, O_RDONLY
);
383 if (fd2
>= 0 || errno
!= ENOENT
) {
384 fprintf(stderr
, "leak at openat of %s\n", tmpname
);
390 int main(int argc
, char *argv
[])
395 if (geteuid() != 0) {
396 fprintf(stderr
, "Run me as root\n");
401 fprintf(stderr
, "Usage: %s [lxcfs_test_cgroup_path]\n", argv
[0]);
405 /* Try syscalls on the directory and on $directory/cgroup.procs */
406 len
= strlen(argv
[1]) + strlen("/cgroup.procs") + 1;
407 procspath
= alloca(len
);
408 snprintf(procspath
, len
, "%s/cgroup.procs", argv
[1]);
411 test_open(procspath
);
413 test_stat(procspath
);
414 test_access(argv
[1]);
415 test_access(procspath
);
418 test_bind(procspath
);
419 test_bindmount(argv
[1]);
420 test_bindmount(procspath
);
421 test_truncate(argv
[1]);
422 test_truncate(procspath
);
424 test_chdir(procspath
);
425 test_rename(argv
[1]);
426 test_rename(procspath
);
428 test_mkdir(procspath
);
430 test_rmdir(procspath
);
432 test_creat(procspath
);
434 test_link(procspath
);
435 test_unlink(argv
[1]);
436 test_unlink(procspath
);
437 test_symlink(argv
[1]);
438 test_symlink(procspath
);
439 test_readlink(argv
[1]);
440 test_readlink(procspath
);
442 test_chmod(procspath
);
444 test_chown(procspath
);
445 test_lchown(argv
[1]);
446 test_lchown(procspath
);
448 test_mknod(procspath
);
449 test_chroot(argv
[1]);
450 test_chroot(procspath
);
451 test_xattrs(argv
[1]);
452 test_xattrs(procspath
);
453 test_utimes(argv
[1]);
454 test_utimes(procspath
);
456 test_openat(argv
[1]);
457 // meh... linkat etc?
459 printf("All tests passed\n");