1 /* 2 * Copyright (c) Crackerjack Project., 2007-2008 ,Hitachi, Ltd 3 * Author(s): Takahiro Yasui <takahiro.yasui.mp (at) hitachi.com>, 4 * Yumiko Sugita <yumiko.sugita.yf (at) hitachi.com>, 5 * Satoshi Fujiwara <sa-fuji (at) sdl.hitachi.co.jp> 6 * Copyright (c) 2016 Linux Test Project 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it would be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23 #include <errno.h> 24 #include <pwd.h> 25 #include <mqueue.h> 26 27 #include "tst_test.h" 28 #include "tst_safe_posix_ipc.h" 29 30 #define QUEUE_NAME "/test_mqueue" 31 32 static uid_t euid; 33 static struct passwd *pw; 34 35 struct test_case { 36 int as_nobody; 37 char *qname; 38 int ret; 39 int err; 40 }; 41 42 static struct test_case tcase[] = { 43 { 44 .qname = QUEUE_NAME, 45 .ret = 0, 46 .err = 0, 47 }, 48 { 49 .as_nobody = 1, 50 .qname = QUEUE_NAME, 51 .ret = -1, 52 .err = EACCES, 53 }, 54 { 55 .qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 56 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 57 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 58 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 59 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 60 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 61 "aaaaaaaaaaaaaaa", 62 .ret = -1, 63 .err = ENOENT, 64 }, 65 { 66 .qname = "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 67 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 68 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 69 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 70 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 71 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 72 "aaaaaaaaaaaaaaaa", 73 .ret = -1, 74 .err = ENAMETOOLONG, 75 }, 76 }; 77 78 void setup(void) 79 { 80 euid = geteuid(); 81 pw = SAFE_GETPWNAM("nobody"); 82 } 83 84 static void do_test(unsigned int i) 85 { 86 struct test_case *tc = &tcase[i]; 87 mqd_t fd; 88 89 tst_res(TINFO, "queue name %s", tc->qname); 90 91 /* 92 * When test ended with SIGTERM etc, mq descriptor is left remains. 93 * So we delete it first. 94 */ 95 mq_unlink(QUEUE_NAME); 96 97 /* prepare */ 98 fd = SAFE_MQ_OPEN(QUEUE_NAME, O_CREAT | O_EXCL | O_RDWR, S_IRWXU, NULL); 99 100 if (tc->as_nobody && seteuid(pw->pw_uid)) { 101 tst_res(TBROK | TERRNO, "seteuid failed"); 102 goto EXIT; 103 } 104 105 /* test */ 106 TEST(mq_unlink(tc->qname)); 107 if (TST_ERR != tc->err || TST_RET != tc->ret) { 108 tst_res(TFAIL | TTERRNO, "mq_unlink returned %ld, expected %d," 109 " expected errno %s (%d)", TST_RET, 110 tc->ret, tst_strerrno(tc->err), tc->err); 111 } else { 112 tst_res(TPASS | TTERRNO, "mq_unlink returned %ld", TST_RET); 113 } 114 115 EXIT: 116 /* cleanup */ 117 if (tc->as_nobody && seteuid(euid) == -1) 118 tst_res(TWARN | TERRNO, "seteuid back to %d failed", euid); 119 120 if (fd > 0 && close(fd)) 121 tst_res(TWARN | TERRNO, "close(fd) failed"); 122 123 mq_unlink(QUEUE_NAME); 124 } 125 126 static struct tst_test test = { 127 .tcnt = ARRAY_SIZE(tcase), 128 .test = do_test, 129 .needs_root = 1, 130 .setup = setup, 131 }; 132