# ls -l /dev crw-rw-r-- 1 admin123 root 45, 255 Jul 29 01:42 isdninfo crw-rw-r-- 1 admin123 root 1, 2 Jul 29 01:42 kmem lrwxrwxrwx 1 admin123 root 12 Jul 29 01:42 log -> /var/log/log crw-rw-r-- 1 admin123 root 1, 1 Jul 29 01:42 mem brw-rw-r-- 1 admin123 root 31, 0 Jul 29 01:42 mtdblock0 brw-rw-r-- 1 admin123 root 31, 1 Jul 29 01:42 mtdblock1 # # ls -l /var srwxr-xr-x 1 admin123 root 0 Jul 29 22:30 rtpproxy.sock drwxr-xr-x 2 admin123 root 0 Jul 29 22:30 run -rw-r--r-- 1 admin123 root 2 Jul 29 22:30 runhttpd drwxr-xr-x 4 admin123 root 0 Jan 1 2011 samba -rw------- 1 admin123 root 8192 Jan 1 2011 secrets.tdb drwxr-x--- 3 admin123 root 0 Jul 30 02:13 ser prw-rw---- 1 admin123 root 0 Jul 30 03:19 ser_fifo
[quagga@localhost socket]$ ls -l openfile.c -rw-rw---- 1 zhang zhang 1770 2012-07-29 21:15 openfile.c [zhang@localhost ctest]$ ls -l | grep socket drwxr-xrwx 3 zhang zhang 4096 2012-07-31 10:13 socket
[quagga@localhost socket]$ ls -l mycat -rwxrwxr-x 1 zhang zhang 7421 2012-07-29 21:16 mycat [quagga@localhost socket]$ [quagga@localhost socket]$ ls -l openfile.c -rw-rw---- 1 zhang zhang 1770 2012-07-29 21:15 openfile.c
[quagga@localhost socket]$ id root uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) [quagga@localhost socket]$ [quagga@localhost socket]$ id zhang uid=500(zhang) gid=500(zhang) groups=500(zhang) [quagga@localhost socket]$ [quagga@localhost socket]$ id quagga uid=501(quagga) gid=501(quagga) groups=501(quagga) [quagga@localhost socket]$
[quagga@localhost socket]$ ls -l openfile.c -rw-rw---- 1 zhang zhang 1770 2012-07-29 21:15 openfile.c [quagga@localhost socket]$ [quagga@localhost socket]$ ls -l mycat -rwxrwxr-x 1 zhang zhang 7421 2012-07-29 21:16 mycat [quagga@localhost socket]$ [quagga@localhost socket]$ which cat /bin/cat [quagga@localhost socket]$ ls -l /bin/cat -rwxr-xr-x 1 root root 55184 2009-03-02 21:57 cat [quagga@localhost socket]$ [quagga@localhost socket]$ cat openfile.c cat: openfile.c: Permission denied [quagga@localhost socket]$ [quagga@localhost socket]$ ./mycat openfile.c cannot open openfile.c[quagga@localhost socket]$
[zhang@localhost socket]$ ls -l openfile.c -rw-rw---- 1 zhang zhang 1770 2012-07-29 21:15 openfile.c [zhang@localhost socket]$ [zhang@localhost socket]$ ls -l mycat -rwxrwxr-x 1 zhang zhang 7421 2012-07-29 21:16 mycat [zhang@localhost socket]$ [zhang@localhost socket]$ chmod u+s mycat [zhang@localhost socket]$ [zhang@localhost socket]$ ls -l mycat -rwsrwxr-x 1 zhang zhang 7421 2012-07-29 21:16 mycat [zhang@localhost socket]$
[openfile.c-43]: sockfd[1]=4, fd=3 [my_open-78]: sockfd[0]=3, sockfd[1]=4, fd=4, c=x /* * this program is excuted by program of "mycat", * execl("./openfile", "openfile", argsockfd, pathname, argmode, (char *) NULL); * */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd); int main(int argc, char **argv) { int fd = -1, n = 0; char buf[10240] = {0}; if (argc != 4) { fprintf(stderr, "openfile <sockfd#> <filename> <mode>\n"); exit(255); } if ( (fd = open(argv[2], atoi(argv[3]))) < 0 ) { exit( (errno > 0) ? errno : 255 ); } /* n = read(fd, buf, sizeof(buf)); write(STDOUT_FILENO, buf, n); */ if ( write_fd(atoi(argv[1]), "x", 1, fd) < 0 ) // if ( write(atoi(argv[1]), &fd, sizeof(int)) < 0 ) { exit( (errno > 0) ? errno : 255 ); } fprintf(stderr, "[%s-%d]: sockfd[1]=%d, fd=%d\n", __FILE__, __LINE__, atoi(argv[1]), fd ); exit(0); } ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd) { struct msghdr msg; struct iovec iov[1]; #if 1 union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(int)); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; *((int *) CMSG_DATA(cmptr)) = sendfd; #else msg.msg_accrights = (caddr_t) &sendfd; msg.msg_accrightslen = sizeof(int); #endif msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; return(sendmsg(fd, &msg, 0)); }
[quagga@localhost socket]$
cr--r----- 1 root system 2, 1 May 25 1998 kmem但ps等程序要读这个文件,而ps的权限设置如下:
-r-xr-sr-x 1 bin system 59346 Apr 05 1998 ps这是一个设置了SGID的程序,而ps的用户是bin,不是root,所以不能设置SUID来访问kmem,但大家注意了,
[zhang@localhost ctest]$ whoami zhang [zhang@localhost ctest]$ chmod o+w socket [zhang@localhost ctest]$ ls -l | grep socket drwxr-xrwx 3 zhang zhang 4096 2012-07-31 10:12 socket [zhang@localhost ctest]$ chmod g+s socket [zhang@localhost ctest]$ [zhang@localhost ctest]$ ls -l | grep socket drwxr-srwx 3 zhang zhang 4096 2012-07-31 10:13 socket [quagga@localhost socket]$ whoami quagga [quagga@localhost socket]$ touch quagga [quagga@localhost socket]$ ls -l quagga -rw-rw-r-- 1 quagga zhang 0 2012-07-31 11:56 quagga [quagga@localhost socket]$
[zhang@localhost ctest]$ whoami zhang [zhang@localhost ctest]$ chmod g-s socket [zhang@localhost ctest]$ ls -l | grep socket drwxr-xrwx 3 zhang zhang 4096 2012-07-31 11:56 socket [zhang@localhost ctest]$ [quagga@localhost socket]$ whoami quagga [quagga@localhost socket]$ touch quagga1 [quagga@localhost socket]$ ls -l quagga* -rw-rw-r-- 1 quagga zhang 0 2012-07-31 11:56 quagga -rw-rw-r-- 1 quagga quagga 0 2012-07-31 11:57 quagga1 [quagga@localhost socket]$ [quagga@localhost socket]$
附录:
mycat.c 源码:
/* * file name: mycat.c * this program is from <unix network program(volume 1 third edition)> 15.7 "unix domain socket" */ #include <stdio.h> #include <stdlib.h> // for exit #include <unistd.h> // for write #include <sys/wait.h> // for WEXITSTATUS #include <sys/un.h> // for socketpair #include <sys/socket.h> // for socketpair #include <sys/types.h> #include <sys/stat.h> //for open #include <fcntl.h> #include <errno.h> int my_open(const char *pathname, int mode); ssize_t read_fd(int fd, void *ptr, size_t nbytes, int *recvfd); int main(int argc, char **argv) { int fd, n; char buf[10240]; if (argc != 2) { fprintf(stderr, "usage: mycat <pathname>.\n"); return 0; } if ( (fd = my_open(argv[1], O_RDONLY)) < 0) { fprintf(stderr, "cannot open %s", argv[1]); return 0; } // while ( (n = read(fd, buf, sizeof(buf))) > 0) if( (n = read(fd, buf, sizeof(buf))) > 0) { write(STDOUT_FILENO, buf, n); } else { perror("read\n"); } exit(0); } int my_open(const char *pathname, int mode) { int fd, sockfd[2], status; pid_t childpid; char c, argsockfd[10], argmode[10]; socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd); if ( (childpid = fork()) == 0) /* child process */ { close(sockfd[0]); snprintf(argsockfd, sizeof(argsockfd), "%d", sockfd[1]); snprintf(argmode, sizeof(argmode), "%d", mode); execl("./openfile", "openfile", argsockfd, pathname, argmode, (char *) NULL); fprintf(stderr, "execl error.\n"); } /* parent process */ close(sockfd[1]); /* wait for the child to terminate */ waitpid(childpid, &status, 0); if (WIFEXITED(status) == 0) { fprintf(stderr, "child did not terminate.\n"); return 0; } if ( (status = WEXITSTATUS(status)) == 0) { read_fd(sockfd[0], &c, 1, &fd); //read(sockfd[0], &fd, sizeof(int)); fprintf(stderr, "[%s-%d]: sockfd[0]=%d, sockfd[1]=%d, fd=%d, c=%c\n", __FUNCTION__, __LINE__, sockfd[0], sockfd[1], fd, c ); } else { errno = status; /* set errno value from child's status */ fd = -1; } close(sockfd[0]); return(fd); } ssize_t read_fd(int fd, void *ptr, size_t nbytes, int *recvfd) { struct msghdr msg; struct iovec iov[1]; ssize_t n; #if 1 union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); #else int newfd; msg.msg_accrights = (caddr_t) &newfd; msg.msg_accrightslen = sizeof(int); #endif msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; if ( (n = recvmsg(fd, &msg, 0)) <= 0) return(n); #if 1 if ( (cmptr = CMSG_FIRSTHDR(&msg)) != NULL && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) { if (cmptr->cmsg_level != SOL_SOCKET) { fprintf(stderr, "control level != SOL_SOCKET\n"); } if (cmptr->cmsg_type != SCM_RIGHTS) { fprintf(stderr, "control type != SCM_RIGHTS\n"); } *recvfd = *((int *) CMSG_DATA(cmptr)); } else { *recvfd = -1; /* descriptor was not passed */ } #else /* *INDENT-OFF* */ if (msg.msg_accrightslen == sizeof(int)) *recvfd = newfd; else *recvfd = -1; /* descriptor was not passed */ /* *INDENT-ON* */ #endif return(n); }
openfile.c源码:
/* * file name: openfile.c * this program is excuted by program of "mycat", * execl("./openfile", "openfile", argsockfd, pathname, argmode, (char *) NULL); * */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd); int main(int argc, char **argv) { int fd = -1, n = 0; char buf[10240] = {0}; if (argc != 4) { fprintf(stderr, "openfile <sockfd#> <filename> <mode>\n"); exit(255); } if ( (fd = open(argv[2], atoi(argv[3]))) < 0 ) { exit( (errno > 0) ? errno : 255 ); } /* n = read(fd, buf, sizeof(buf)); write(STDOUT_FILENO, buf, n); */ if ( write_fd(atoi(argv[1]), "x", 1, fd) < 0 ) // if ( write(atoi(argv[1]), &fd, sizeof(int)) < 0 ) { exit( (errno > 0) ? errno : 255 ); } fprintf(stderr, "[%s-%d]: sockfd[1]=%d, fd=%d\n", __FILE__, __LINE__, atoi(argv[1]), fd ); exit(0); } ssize_t write_fd(int fd, void *ptr, size_t nbytes, int sendfd) { struct msghdr msg; struct iovec iov[1]; #if 1 union { struct cmsghdr cm; char control[CMSG_SPACE(sizeof(int))]; } control_un; struct cmsghdr *cmptr; msg.msg_control = control_un.control; msg.msg_controllen = sizeof(control_un.control); cmptr = CMSG_FIRSTHDR(&msg); cmptr->cmsg_len = CMSG_LEN(sizeof(int)); cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; *((int *) CMSG_DATA(cmptr)) = sendfd; #else msg.msg_accrights = (caddr_t) &sendfd; msg.msg_accrightslen = sizeof(int); #endif msg.msg_name = NULL; msg.msg_namelen = 0; iov[0].iov_base = ptr; iov[0].iov_len = nbytes; msg.msg_iov = iov; msg.msg_iovlen = 1; return(sendmsg(fd, &msg, 0)); }