10eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin/* 20eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * Check decoding of setresuid/setresgid/setresuid32/setresgid32 syscalls. 30eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * 40eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org> 50eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * All rights reserved. 60eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * 70eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * Redistribution and use in source and binary forms, with or without 80eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * modification, are permitted provided that the following conditions 90eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * are met: 100eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * 1. Redistributions of source code must retain the above copyright 110eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * notice, this list of conditions and the following disclaimer. 120eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * 2. Redistributions in binary form must reproduce the above copyright 130eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * notice, this list of conditions and the following disclaimer in the 140eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * documentation and/or other materials provided with the distribution. 150eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * 3. The name of the author may not be used to endorse or promote products 160eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * derived from this software without specific prior written permission. 170eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * 180eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 190eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 200eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 210eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 220eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 230eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 240eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 250eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 260eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 270eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 280eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin */ 290eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 300eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin#include <errno.h> 310eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin#include <stdio.h> 320eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin#include <unistd.h> 330eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 340eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levinstatic int 350eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levinugid2int(const unsigned UGID_TYPE ugid) 360eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin{ 370eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin if ((unsigned UGID_TYPE) -1U == ugid) 380eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin return -1; 390eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin else 400eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin return ugid; 410eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin} 420eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 430eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levinstatic void 440eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levinprint_int(const unsigned int num) 450eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin{ 460eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin if (num == -1U) 470eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin printf("-1"); 480eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin else 490eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin printf("%u", num); 500eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin} 510eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 520eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levinstatic int 530eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levinnum_matches_id(const unsigned int num, const unsigned int ugid) 540eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin{ 550eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin return num == ugid || num == -1U; 560eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin} 570eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 580eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin#define TRIPLE(val) \ 590eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin { val, ugid, ugid }, { ugid, val, ugid }, { ugid, ugid, val } 600eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 610eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levinint 620eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levinmain(void) 630eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin{ 640eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin unsigned int ugid = GETUGID; 650eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin CHECK_OVERFLOWUGID(ugid); 660eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 670eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin const struct { 680eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin const long r, e, s; 690eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin } tests[] = { 700eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin { ugid, ugid, ugid }, 710eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin TRIPLE((unsigned long) 0xffffffff00000000ULL | ugid), 720eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin TRIPLE(-1U), 730eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin TRIPLE(-1L), 740eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin TRIPLE(0xffff0000U | ugid), 750eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin TRIPLE(0xffff), 760eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin TRIPLE(0xc0deffffU) 770eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin }; 780eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 790eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin unsigned int i; 800eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 810eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin for (i = 0; i < ARRAY_SIZE(tests); ++i) { 820eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin const unsigned int rn = ugid2int(tests[i].r); 830eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin const unsigned int en = ugid2int(tests[i].e); 840eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin const unsigned int sn = ugid2int(tests[i].s); 850eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 860eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin if (!num_matches_id(rn, ugid) || 870eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin !num_matches_id(en, ugid) || 880eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin !num_matches_id(sn, ugid)) 890eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin continue; 900eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 910eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin if (syscall(SYSCALL_NR, tests[i].r, tests[i].e, tests[i].s)) { 920eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin if (!i && ENOSYS == errno) { 930eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin printf("%s(%u, %u, %u) = -1 ENOSYS (%m)\n", 940eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin SYSCALL_NAME, ugid, ugid, ugid); 950eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin break; 960eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin } 970eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin perror_msg_and_fail("%s(%#lx, %#lx, %#lx)", 980eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin SYSCALL_NAME, 990eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin tests[i].r, tests[i].e, tests[i].s); 1000eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin } 1010eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 1020eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin printf("%s(", SYSCALL_NAME); 1030eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin print_int(rn); 1040eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin printf(", "); 1050eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin print_int(en); 1060eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin printf(", "); 1070eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin print_int(sn); 1080eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin printf(") = 0\n"); 1090eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin } 1100eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin 1110eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin puts("+++ exited with 0 +++"); 1120eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin return 0; 1130eac88a00a3a96640b5d686788bd9a68edb43cc5Dmitry V. Levin} 114