Andrew,

Your thoughts on this ;-)

--Subrata

> 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


-------------------------------------------------------------------------
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