On Mon, 2008-02-04 at 21:53 -0600, Serge E. Hallyn wrote:
> Hi Andrew,
> 
> The original verify_caps_exec.c test in the filecaps test was written
> before libcap had file capabilities support.  Faced with implementing
> 64-bit support in that ugly mess in order to properly test your
> per-process securebits patch, it seemed wise to just switch to using
> libcap :)  Does the following new version of the file look kosher
> to you?

Hi Andrew,

Can you please provide your comments on this test case from Sergei? We
are looking forward, and, would be happy to see this inside LTP post
comments.

Regards--
Subrata

> 
> thanks,
> -serge
> 
> /******************************************************************************/
> /*                                                                            
> */
> /* Copyright (c) International Business Machines  Corp., 2007, 2008           
> */
> /*                                                                            
> */
> /* This program is free software;  you can redistribute it and/or modify      
> */
> /* it under the terms of the GNU General Public License as published by       
> */
> /* the Free Software Foundation; either version 2 of the License, or          
> */
> /* (at your option) any later version.                                        
> */
> /*                                                                            
> */
> /* This program is distributed in the hope that it will be useful,            
> */
> /* but WITHOUT ANY WARRANTY;  without even the implied warranty of            
> */
> /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                  
> */
> /* the GNU General Public License for more details.                           
> */
> /*                                                                            
> */
> /* You should have received a copy of the GNU General Public License          
> */
> /* along with this program;  if not, write to the Free Software               
> */
> /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA    
> */
> /*                                                                            
> */
> /******************************************************************************/
> /*
>  * File: verify_caps_exec.c
>  * Author: Serge Hallyn
>  * Purpose: perform several tests of file capabilities:
>  *  1. try setting caps without CAP_SYS_ADMIN
>  *  2. test proper calculation of pI', pE', and pP'.
>  *     Try setting valid caps, drop rights, and run the executable,
>  *     make sure we get the rights
>  */
> 
> #define _GNU_SOURCE
> #include <stdio.h>
> #include <unistd.h>
> #include <endian.h>
> #include <byteswap.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <sys/wait.h>
> #include <errno.h>
> #include <fcntl.h>
> #include <sys/capability.h>
> #include <sys/prctl.h>
> #include <test.h>
> 
> #define TSTPATH "./print_caps"
> char *TCID = "filecaps";
> int TST_TOTAL=1;
> 
> int errno;
> 
> void usage(char *me)
> {
>       tst_resm(TFAIL, "Usage: %s <0|1> [arg]\n", me);
>       tst_resm(TINFO, "  0: set file caps without CAP_SYS_ADMIN\n");
>       tst_resm(TINFO, "  1: test that file caps are set correctly on exec\n");
>       tst_exit(1);
> }
> 
> #define DROP_PERMS 0
> #define KEEP_PERMS 1
> 
> void print_my_caps()
> {
>       cap_t cap = cap_get_proc();
>       tst_resm(TINFO, "\ncaps are %s\n", cap_to_text(cap, NULL));
> }
> 
> int drop_root(int keep_perms)
> {
>       int ret;
> 
>       if (keep_perms)
>               prctl(PR_SET_KEEPCAPS, 1);
>       ret = setresuid(1000, 1000, 1000);
>       if (ret) {
>               perror("setresuid");
>               tst_resm(TFAIL, "Error dropping root privs\n");
>               tst_exit(4);
>       }
>       if (keep_perms) {
>               cap_t cap = cap_from_text("=eip");
>               cap_set_proc(cap);
>       }
> 
>       return 1;
> }
> 
> /*
>  * TODO: find a better way to do this.  Emulate libcap's
>  * way, or just take it from linux/capability.h
>  */
> #ifndef __CAP_BITS
> #define __CAP_BITS 34
> #endif
> 
> int perms_test(void)
> {
>       int ret;
>       cap_t cap;
> 
>       drop_root(DROP_PERMS);
>       cap = cap_from_text("all=eip");
>       if (!cap) {
>               tst_resm(TFAIL, "could not get cap from text for perms test\n");
>               return 1;
>       }
>       ret = cap_set_file(TSTPATH, cap);
>       if (ret) {
>               tst_resm(TPASS, "could not set capabilities as non-root\n");
>               ret = 0;
>       } else {
>               tst_resm(TFAIL, "could set capabilities as non-root\n");
>               ret = 1;
>       }
> 
>       cap_free(cap);
>       return ret;
> }
> 
> #define FIFOFILE "caps_fifo"
> void create_fifo(void)
> {
>       int ret;
> 
>       ret = mkfifo(FIFOFILE, S_IRWXU | S_IRWXG | S_IRWXO);
>       if (ret == -1 && errno != EEXIST) {
>               perror("mkfifo");
>               tst_resm(TFAIL, "failed creating %s\n", FIFOFILE);
>               tst_exit(1);
>       }
> }
> 
> void write_to_fifo(char *buf)
> {
>       int fd;
> 
>       fd = open(FIFOFILE, O_WRONLY);
>       write(fd, buf, strlen(buf));
>       close(fd);
> }
> 
> void read_from_fifo(char *buf)
> {
>       int fd;
> 
>       memset(buf, 0, 200);
>       fd = open(FIFOFILE, O_RDONLY);
>       if (fd < 0) {
>               perror("open");
>               tst_resm(TFAIL, "Failed opening fifo\n");
>               tst_exit(1);
>       }
>       read(fd, buf, 199);
>       close(fd);
> }
> 
> int compare_caps(char *buf1, char *buf2)
> {
>       int res;
> 
>       res = strcmp(buf1, buf2) == 0;
>       return res;
> }
> 
> int fork_drop_and_exec(int keepperms, char *capstxt)
> {
>       int pid;
>       int ret = 0;
>       char buf[200], *p;
>       static int seqno = 0;
> 
>       pid = fork();
>       if (pid < 0) {
>               perror("fork");
>               tst_resm(TFAIL, "%s: failed fork\n", __FUNCTION__);
>               tst_exit(1);
>       }
>       if (pid == 0) {
>               drop_root(keepperms);
>               print_my_caps();
>               sprintf(buf, "%d", seqno);
>               ret = execlp(TSTPATH, TSTPATH, buf, NULL);
>               perror("execl");
>               tst_resm(TFAIL, "%s: exec failed\n", __FUNCTION__);
>               snprintf(buf, 200, "failed to run as %s\n", capstxt);
>               write_to_fifo(buf);
>               tst_exit(1);
>       } else {
>               p = buf;
>               while (1) {
>                       int c, s;
>                       read_from_fifo(buf);
>                       c = sscanf(buf, "%d", &s);
>                       if (c==1 && s==seqno)
>                               break;
>                       tst_resm(TINFO, "got a bad seqno (c=%d, s=%d, 
> seqno=%d)",
>                               c, s, seqno);
>               }
>               p = index(buf, '.')+1;
>               if (p==(char *)1) {
>                       tst_resm(TFAIL, "got a bad message from print_caps\n");
>                       tst_exit(1);
>               }
>               tst_resm(TINFO, "Expected to run as .%s., ran as .%s..\n",
>                       capstxt, p);
>               if (strcmp(p, capstxt) != 0) {
>                       tst_resm(TINFO, "those are not the same\n");
>                       ret = -1;
>               }
>               seqno++;
>       }
>       return ret;
> }
> 
> int caps_actually_set_test(void)
> {
>       int  whichset, whichcap, finalret = 0, ret;
>       cap_t cap, pcap;
>       char *capstxt;
>       cap_value_t capvalue[1];
> 
>       cap = cap_init();
>       pcap = cap_init();
>       if (!cap || !pcap) {
>               perror("cap_init");
>               exit(2);
>       }
> 
>       create_fifo();
> 
>       /* first, try each bit in fP (forced) with fE on and off. */
>       for (whichcap=0; whichcap < __CAP_BITS; whichcap++) {
>               /* fE = 0, don't gain the perm */
>               capvalue[0] = whichcap;
>               cap_clear(cap);
>               cap_set_flag(cap, CAP_PERMITTED, 1, capvalue, CAP_SET);
>               ret = cap_set_file(TSTPATH, cap);
>               if (ret) {
>                       tst_resm(TINFO, "%d %d\n", whichset, whichcap);
>                       continue;
>               }
>               capstxt = cap_to_text(cap, NULL);
>               ret = fork_drop_and_exec(DROP_PERMS, capstxt);
>               if (ret) {
>                       tst_resm(TINFO, "Failed CAP_PERMITTED=%d 
> CAP_EFFECTIVE=0\n",
>                                       whichcap);
>                       if (!finalret)
>                               finalret = ret;
>               }
> 
> /* SERGE here */
>               /* fE = 1, do gain the perm */
>               cap_clear(cap);
>               cap_set_flag(cap, CAP_PERMITTED, 1, capvalue, CAP_SET);
>               cap_set_flag(cap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
>               ret = cap_set_file(TSTPATH, cap);
>               if (ret) {
>                       tst_resm(TINFO, "%d %d\n", whichset, whichcap);
>                       continue;
>               }
>               capstxt = cap_to_text(cap, NULL);
>               if (strcmp(capstxt, "=")==0) {
>                       tst_resm(TINFO, "%s: libcap doesn't know about cap %d, 
> not running\n",
>                               __FUNCTION__, whichcap);
>                       ret = 0;
>               } else
>                       ret = fork_drop_and_exec(DROP_PERMS, capstxt);
>               if (ret) {
>                       tst_resm(TINFO, "Failed CAP_PERMITTED=%d 
> CAP_EFFECTIVE=1\n",
>                               whichcap);
>                       if (!finalret)
>                               finalret = ret;
>               }
>       }
> 
> 
>       /*
>        * next try each bit in fI
>        * The first two attemps have the bit which is in fI in pI.
>        *     This should result in the bit being in pP'.
>        *     If fE was set then it should also be in pE'.
>        * The last attempt starts with an empty pI.
>        *     This should result in empty capability, as there were
>        *     no bits to be inherited from the original process.
>        */
>       for (whichcap=0; whichcap < __CAP_BITS; whichcap++) {
>               int i;
>               /*
>                * bit is in fI and pI, so should be in pI'.
>                * but fE=0, so cap is in pP' but not pE'.
>                */
>               cap_clear(cap);
>               cap_clear(pcap);
>               for (i=0; i<__CAP_BITS; i++) {
>                       capvalue[0] = i;
>                       cap_set_flag(pcap, CAP_INHERITABLE, 1, capvalue, 
> CAP_SET);
>               }
>               capvalue[0] = whichcap;
>               cap_set_flag(cap, CAP_INHERITABLE, 1, capvalue, CAP_SET);
>               ret = cap_set_file(TSTPATH, cap);
>               if (ret) {
>                       tst_resm(TINFO, "%d %d\n", whichset, whichcap);
>                       continue;
>               }
>               cap_set_flag(pcap, CAP_PERMITTED, 1, capvalue, CAP_SET);
>               capstxt = cap_to_text(pcap, NULL);
>               ret = fork_drop_and_exec(KEEP_PERMS,  capstxt);
>               if (ret) {
>                       tst_resm(TINFO, "Failed with_perms CAP_INHERITABLE=%d "
>                                       "CAP_EFFECTIVE=0\n", whichcap);
>                       if (!finalret)
>                               finalret = ret;
>               }
> 
>               /*
>                * bit is in fI and pI, so should be in pI'.
>                * and fE=1, so cap is in pP' and pE'.
>                */
> 
>               cap_set_flag(cap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
>               ret = cap_set_file(TSTPATH, cap);
>               if (ret) {
>                       tst_resm(TINFO, "%d %d\n", whichset, whichcap);
>                       continue;
>               }
>               cap_set_flag(pcap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
>               capstxt = cap_to_text(pcap, NULL);
>               if (strcmp(capstxt, "=")==0) {
>                       tst_resm(TINFO, "%s: libcap doesn't know about cap %d, 
> not running\n",
>                               __FUNCTION__, whichcap);
>                       ret = 0;
>               } else
>                       ret = fork_drop_and_exec(KEEP_PERMS, capstxt);
>               if (ret) {
>                       tst_resm(TINFO, "Failed with_perms CAP_INHERITABLE=%d "
>                                       "CAP_EFFECTIVE=1\n", whichcap);
>                       if (!finalret)
>                               finalret = ret;
>               }
> 
>               /*
>                * bit is in fI but not in pI
>                * So pP' is empty.
>                * pE' must be empty.
>                */
>               cap_clear(cap);
>               capstxt = cap_to_text(cap, NULL);
>               ret = fork_drop_and_exec(DROP_PERMS, capstxt);
>               if (ret) {
>                       tst_resm(TINFO, "Failed without_perms 
> CAP_INHERITABLE=%d",
>                                       whichcap);
>                       if (!finalret)
>                               finalret = ret;
>               }
>       }
> 
>       cap_free(cap);
>       return finalret;
> }
> 
> int main(int argc, char *argv[])
> {
>       int ret = 0;
> 
>       if (argc < 2)
>               usage(argv[0]);
> 
>       switch(atoi(argv[1])) {
>               case 0:
>                       ret = perms_test();
>                       break;
>               case 1:
>                       ret = caps_actually_set_test();
>                       if (ret)
>                               tst_resm(TFAIL, "Some tests failed\n");
>                       else
>                               tst_resm(TPASS, "All tests passed\n");
>                       break;
>               default: usage(argv[0]);
>       }
> 
>       tst_exit(ret);
> }
> 
> -------------------------------------------------------------------------
> This SF.net email is sponsored by: Microsoft
> Defy all challenges. Microsoft(R) Visual Studio 2008.
> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
> _______________________________________________
> Ltp-list mailing list
> Ltp-list@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/ltp-list


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to