免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 18687 | 回复: 0
打印 上一主题 下一主题

[Linux] 使用clone函数+CLONE_NEWNS函数创建挂载命名空间,为啥别的进程还是能看见挂载信息 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2022-05-26 14:46 |只看该作者 |倒序浏览
我的目标是用一个进程创建新的命名空间,在这个进程里做mount操作,达到只有同命名空间里的进程能看到挂载情况的目的。可是,这个效果就是没有,执行进程后,shell 里执行ls ,还是能看到挂载的文件。这是怎么回事呢?请高手指点!

代码如下:
  1. #define _GNU_SOURCE
  2. #include <stdio.h>                /* for convenience */
  3. #include <stdlib.h>                /* for convenience */
  4. #include <string.h>                /* for convenience */
  5. #include <unistd.h>                /* for convenience */
  6. #include <errno.h>
  7. #include <pwd.h>
  8. #include <sched.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <fcntl.h>
  12. #include <sys/wait.h>
  13. #include <sys/mount.h>


  14. #define MAXLINE 10


  15. /*若某字符串中有多个空格,tab标志,换行符或者回车符 */
  16. /*且这些字符可能接连出现,则将此字符串中的多个连续的*/
  17. /*不可显示字符压缩为一个空格*/
  18. /*参数len看似多余,其实有大用。如果源址与目的地址*/
  19. /*重叠的情况下,可消除可能出现的死循环*/
  20. void shrink(char *src,char *dest,size_t len)
  21. {
  22.         int i= 0,j=0;
  23.         int n= 0;
  24.         int spacelen = 0;
  25.         while( (src[i]!='\0') && n<=len )
  26.         {
  27.                 if( (src[i]==32)||(src[i]==9)||(src[i]==10) )
  28.                 {
  29.                         if(spacelen==0)
  30.                         {
  31.                                 dest[j]=' ';
  32.                                 spacelen++;
  33.                                 i++;
  34.                                 j++;
  35.                         }
  36.                         else
  37.                                 i++;
  38.                         n++;
  39.                         continue;
  40.                 }
  41.                 dest[j]=src[i];
  42.                 i++;
  43.                 j++;
  44.                 n++;
  45.                 spacelen = 0;
  46.         }
  47.         dest[j]='\0';
  48. }





  49. char * my_itoa(int value,char *string,int radix)
  50. {
  51.         char zm[37]="0123456789abcdefghijklmnopqrstuvwxyz";
  52.         char aa[100]={0};

  53.         int sum=value;
  54.         char *cp=string;
  55.         int i=0;
  56.        
  57.         if(radix<2||radix>36)//增加了对错误的检测
  58.         {
  59.                 //cout<<"error data!"<<endl;
  60.                 return string;
  61.         }

  62.         if(value<0)
  63.         {
  64.                 //cout<<"error data!"<<endl;
  65.                 return string;
  66.         }
  67.        

  68.         while(sum>0)
  69.         {
  70.                 aa[i++]=zm[sum%radix];
  71.                 sum/=radix;
  72.         }

  73.         for(int j=i-1;j>=0;j--)
  74.         {
  75.                 *cp++=aa[j];
  76.         }
  77.         *cp='\0';
  78.         return string;
  79. }





  80. //按空格切分字符串。假设sub数组的长度够用
  81. int splitestr(const char *src,char sub[][256],int * argc)
  82. {
  83.         /*split a string by space key*/
  84.         int i=0;
  85.         int j=0;
  86.         int len=0;
  87.         int flag=0;
  88.         char *tmp=NULL;
  89.         while( src[i]!='\0' )
  90.         {
  91.                 if (src[i]!=' ')
  92.                 {
  93.                         i++;
  94.                         len++;
  95.                 }
  96.                 if(src[i]==' ' )
  97.                 {
  98.                         i++;
  99.                         tmp = (char *)&src[flag];
  100.                         strncpy(sub[j],tmp,len);
  101.                         j++;
  102.                         flag = i;
  103.                         len =0;
  104.                 }
  105.         }
  106.         tmp = (char *)&src[flag];
  107.         strncpy(sub[j],tmp,len);
  108.         *argc = j+1;
  109.         return 0;
  110. }


  111. int get_ns_id(pid_t pid,const char *ns_type)
  112. {
  113.     char tmp[20] = {0};
  114.     my_itoa(pid,tmp,10);

  115.     char cmd[50] = {0};
  116.     strcat(cmd,"ls -l /proc/");
  117.     strcat(cmd,tmp);
  118.     strcat(cmd,"/ns/");

  119.     FILE   *stream;
  120.     char buf[1000] = {0};
  121.     stream = popen(cmd, "r" ); //将命令的输出 通过管道读取(“r”参数)到FILE* stream
  122.     fread( buf, sizeof(char), sizeof(buf), stream); //将刚刚FILE* stream的数据流读取到buf中
  123.     pclose( stream );


  124. /*

  125.         mode_t f_attrib = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;   
  126.         char * tmpfile = tmpnam(0);
  127.         printf("tmpfile:%s\n",tmpfile);

  128.         int fd = open(tmpfile, O_RDWR|O_CREAT,f_attrib);

  129.     if(fd == -1)
  130.         perror("open tmpfile error");

  131.     int old_fd=dup(STDOUT_FILENO);  //保存屏幕输出的文件描述符,用于恢复
  132.         dup2(fd,STDOUT_FILENO);         //输出重定向

  133.     char buf[1000] = {0};
  134.         system(cmd);
  135.     read(fd,buf,1000);
  136.     close(fd);
  137.     dup2(old_fd,STDOUT_FILENO);  // 还原屏幕输出默认文件描述符指向

  138. */
  139.     //printf("buf:%s\n",buf);

  140.     char search[20] = {0};
  141.     strcat(search,ns_type);
  142.     strcat(search,"[");

  143.     char *first_pos = strstr(buf,search);
  144.     char *last_pos = strstr(first_pos,"]");
  145.     char ns_name[20] = {0};
  146.     strncpy(ns_name, first_pos+strlen(search), last_pos-(first_pos+strlen(search)) );
  147.     //printf("ns_name:%s\n",ns_name);

  148.     return atoi(ns_name);
  149. }


  150. void my_system(const char * cmd)
  151. {
  152.         char cmd2[200] = {0};
  153.         strcpy(cmd2,cmd);
  154.         shrink(cmd2,cmd2,strlen(cmd2));
  155.        
  156.         pid_t        pid;
  157.         if ((pid = fork()) < 0)
  158.         {
  159.                 perror("fork error\n");
  160.         }
  161.         else if (pid == 0)
  162.         {       
  163.                 setuid(0);

  164.         char path[50] = {0};
  165.         strcat(path,"/proc/");

  166.         char tmp[20] = {0};
  167.         pid_t parent_pid = getppid();
  168.         my_itoa(parent_pid,tmp,10);

  169.         strcat(path,tmp);
  170.         strcat(path,"/ns/mnt");

  171.         //get mount id of parent
  172.         int mnt_fd = open(path,O_RDONLY);
  173.          if (mnt_fd == -1)
  174.                perror("open mnt");

  175.         if (setns(mnt_fd, CLONE_NEWNS) == -1)
  176.             perror("setns error");


  177.         int argc = 0;
  178.         char args[10][256] = {0};
  179.         splitestr(cmd2,args,&argc);


  180.         char * argv[10] = {0};
  181.         for(int i=0;i< argc;i++)
  182.         {
  183.             argv[i] = args[i];
  184.                         printf("%s\n",argv[i]);
  185.         }

  186.                 if (execvp(argv[0], argv) < 0)
  187.                         perror("execl error\n");

  188.         close(mnt_fd);
  189.         }

  190.         if (waitpid(pid, 0, 0) < 0)
  191.                 perror("wait error\n");
  192. }


  193. static char child_stack[1048576];

  194. static int child_fn()
  195. {
  196.     setuid(0);


  197.         //if (unshare(CLONE_NEWNS) < 0)
  198.         //{
  199.         //        perrpr("unshare");
  200.         //}


  201.         char pass[] = {'1','2','3','4','5','6'};
  202.         mode_t f_attrib = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;   
  203.         char * tmpfile = tmpnam(0);
  204.         int fd = open(tmpfile, O_RDWR|O_CREAT,f_attrib);
  205.         write(fd,pass,sizeof(pass));

  206.     int old_fd=dup(STDIN_FILENO);  //保存描述符,用于恢复
  207.         dup2(fd,STDIN_FILENO);
  208.         lseek(0,0,SEEK_SET);

  209.         //char cmd2[100] = {0};
  210.         my_system("cryptsetup luksOpen /home/wxf/dss/sdb1 dss_encrypted_partition");
  211.         close(fd);
  212.         unlink(tmpfile);

  213.     dup2(old_fd,STDIN_FILENO);  // 还原文件描述符

  214.         //my_system("mkfs.ext4 /dev/mapper/dss_encrypted_partition");
  215.         my_system("mount --make-private  /dev/mapper/dss_encrypted_partition /mnt/dssdir");
  216.         //my_system("mount    /dev/mapper/dss_encrypted_partition    /mnt/dssdir");

  217.         while(1)
  218.         {
  219.                 sleep(10);
  220.         }

  221.     return 0;
  222. }



  223. int main(int argc, char *argv[])
  224. {
  225.           pid_t child_pid = clone(child_fn, child_stack+1048576,  CLONE_NEWNS, 0);// 0x00020000   CLONE_NEWNS

  226.     if(child_pid == -1)
  227.         perror("clone error");

  228.           return 0;
  229. }
复制代码



您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP