From d40e50d7c97185466e7c46b2dfff80cefe03e2a6 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 27 Jan 2012 21:45:13 +0400 Subject: [PATCH] zdtm: Tests for xids and caps Rather simple and straightforward and atomic tests should be. The only problem is that after changing any from the subj the subsequent opens for .out/.pid files fail so test actually forks in the beginning. That said -- we need some API in the lib/ for such forkers. Signed-off-by: Pavel Emelyanov Signed-off-by: Cyrill Gorcunov --- test/zdtm.sh | 2 + test/zdtm/live/static/Makefile | 1 + test/zdtm/live/static/caps00.c | 125 +++++++++++++++++++++++++++++++++ test/zdtm/live/static/pid00.c | 96 ++++++++++++++++++------- 4 files changed, 200 insertions(+), 24 deletions(-) create mode 100644 test/zdtm/live/static/caps00.c diff --git a/test/zdtm.sh b/test/zdtm.sh index ffc8504fb..100faf9e7 100644 --- a/test/zdtm.sh +++ b/test/zdtm.sh @@ -25,6 +25,8 @@ $ZP/streaming/pipe_shared00 $ZP/transition/file_read $ZP/transition/fork $ZP/static/zombie00 +$ZP/static/pid00 +$ZP/static/caps00 $ZP/static/cmdlinenv00 $ZP/static/socket_listen" diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile index 7fb1affaa..66227364a 100644 --- a/test/zdtm/live/static/Makefile +++ b/test/zdtm/live/static/Makefile @@ -7,6 +7,7 @@ TST_NOFILE = \ busyloop00 \ sleeping00 \ pid00 \ + caps00 \ wait00 \ zombie00 \ fpu00 \ diff --git a/test/zdtm/live/static/caps00.c b/test/zdtm/live/static/caps00.c new file mode 100644 index 000000000..13832173e --- /dev/null +++ b/test/zdtm/live/static/caps00.c @@ -0,0 +1,125 @@ +#define _GNU_SOURCE +#include +#include +#include + +#include "zdtmtst.h" + +const char *test_doc = "Check that aps are preserved"; +const char *test_author = "Pavel Emelianov "; + +struct cap_hdr { + unsigned int version; + int pid; +}; + +struct cap_data { + unsigned int eff; + unsigned int prm; + unsigned int inh; +}; + +#define _LINUX_CAPABILITY_VERSION_3 0x20080522 +#define _LINUX_CAPABILITY_U32S_3 2 +#define CAP_CHOWN 0 +#define CAP_DAC_OVERRIDE 1 + +int capget(struct cap_hdr *hdrp, struct cap_data *datap); +int capset(struct cap_hdr *hdrp, const struct cap_data *datap); + +int main(int argc, char **argv) +{ + int pid, s_p[2], f_p[2], r_p[3]; + char res = 'x'; + + test_init(argc, argv); + + pipe(s_p); + pipe(f_p); + pipe(r_p); + + pid = fork(); + if (pid == 0) { + struct cap_hdr hdr; + struct cap_data data[_LINUX_CAPABILITY_U32S_3]; + struct cap_data data_2[_LINUX_CAPABILITY_U32S_3]; + + close(s_p[0]); + close(f_p[1]); + close(r_p[0]); + + hdr.version = _LINUX_CAPABILITY_VERSION_3; + hdr.pid = 0; + + capget(&hdr, data); + + hdr.version = _LINUX_CAPABILITY_VERSION_3; + hdr.pid = 0; + + data[0].eff &= ~((1 << CAP_CHOWN) | (1 << CAP_DAC_OVERRIDE)); + data[0].prm &= ~(1 << CAP_DAC_OVERRIDE); + + capset(&hdr, data); + + close(s_p[1]); + + read(f_p[0], &res, 1); + close(f_p[0]); + + hdr.version = _LINUX_CAPABILITY_VERSION_3; + hdr.pid = 0; + + capget(&hdr, data_2); + + if (data[0].eff != data_2[0].eff) { + res = '1'; + goto bad; + } + if (data[1].eff != data_2[1].eff) { + res = '2'; + goto bad; + } + if (data[0].prm != data_2[0].prm) { + res = '3'; + goto bad; + } + if (data[1].prm != data_2[1].prm) { + res = '4'; + goto bad; + } + if (data[0].inh != data_2[0].inh) { + res = '3'; + goto bad; + } + if (data[1].inh != data_2[1].inh) { + res = '4'; + goto bad; + } + + res = '0'; +bad: + write(r_p[1], &res, 1); + close(r_p[1]); + _exit(0); + } + + close(f_p[0]); + close(s_p[1]); + close(r_p[1]); + + read(s_p[0], &res, 1); + close(s_p[0]); + + test_daemon(); + test_waitsig(); + + close(f_p[1]); + + read(r_p[0], &res, 1); + if (res == '0') + pass(); + else + fail("Fail: %c", res); + + return 0; +} diff --git a/test/zdtm/live/static/pid00.c b/test/zdtm/live/static/pid00.c index 030aeda1f..0b03ef596 100644 --- a/test/zdtm/live/static/pid00.c +++ b/test/zdtm/live/static/pid00.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include @@ -7,40 +8,87 @@ const char *test_doc = "Check that p?pid and e?[ug]id didn't change"; const char *test_author = "Pavel Emelianov "; +int setfsuid(uid_t fsuid); +int setfsgid(uid_t fsgid); + int main(int argc, char **argv) { - pid_t pid, ppid; - uid_t uid, euid; - gid_t gid, egid; + int pid, s_p[2], f_p[2], r_p[3]; + const __uid_t w_ruid = 1, w_euid = 2, w_suid = 3, w_fsuid = w_euid; + const __uid_t w_rgid = 5, w_egid = 6, w_sgid = 7, w_fsgid = 8; + __uid_t rid, eid, sid, fsid; + char res = 'x'; test_init(argc, argv); -#define SET_XID(id) id = get##id() - SET_XID(pid); - ppid = 1; /* SET_XID(ppid); daemonization confuses it */ - SET_XID(uid); - SET_XID(euid); - SET_XID(gid); - SET_XID(egid); + pipe(s_p); + pipe(f_p); + pipe(r_p); + + pid = fork(); + if (pid == 0) { + close(s_p[0]); + close(f_p[1]); + close(r_p[0]); + + setresgid(w_rgid, w_egid, w_sgid); + setfsgid(w_fsgid); + setresuid(w_ruid, w_euid, w_suid); + /* fsuid change is impossible after above */ + + close(s_p[1]); + + read(f_p[0], &res, 1); + close(f_p[0]); + +#define CHECK_ID(__t, __w, __e) do { \ + if (__t##id != w_##__t##__w##id) { \ + res = __e; \ + goto bad; \ + } \ + } while (0) + + rid = eid = sid = fsid = 0; + getresuid(&rid, &eid, &sid); + fsid = setfsuid(w_euid); + CHECK_ID(r, u, '1'); + CHECK_ID(e, u, '2'); + CHECK_ID(s, u, '3'); + CHECK_ID(s, u, '3'); + CHECK_ID(fs, u, '4'); + + rid = eid = sid = fsid = 0; + getresgid(&rid, &eid, &sid); + fsid = setfsgid(w_fsgid); + CHECK_ID(r, g, '5'); + CHECK_ID(e, g, '6'); + CHECK_ID(s, g, '7'); + CHECK_ID(fs, g, '8'); + + res = '0'; +bad: + write(r_p[1], &res, 1); + close(r_p[1]); + _exit(0); + } + + close(f_p[0]); + close(s_p[1]); + close(r_p[1]); + + read(s_p[0], &res, 1); + close(s_p[0]); test_daemon(); test_waitsig(); -#define CHECK(id) do { \ - if (id != get##id()) { \ - fail("%s != get%s()\n", #id, #id); \ - goto out; \ - } \ -} while (0) + close(f_p[1]); - CHECK(pid); - CHECK(ppid); - CHECK(uid); - CHECK(euid); - CHECK(gid); - CHECK(egid); + read(r_p[0], &res, 1); + if (res == '0') + pass(); + else + fail("Fail: %c", res); - pass(); -out: return 0; }