|

楼主 |
发表于 2003-5-2 11:27:12
|
显示全部楼层
#############################################################################
对于 LFS 的专门指导
#############################################################################
对于 package user 的用户名,我通常使用软件包的名称,不包含版本号,但包含横线,名字可以长于8个字符,比如"util-linux".
除了 ls -l 会去掉用户名中最后的字符以外,我还没有碰到什么问题。我测试过的其他程序都能正确处理这样的用户名。如果你遇到了问题,请告诉我。
那么,我们应该怎样在编译 LFS 系统的时候用上面的方法呢?
##########################################################################
chroot 以前的阶段
##########################################################################
在 chroot 前我们不使用 package users.但这并不意味着我们要用 root 来安装。我建议用普通用户来安装 chroot 前的系统。这样,在最后你就能分辨在 chroot 环境中创建的文件 (它们的 uid 是 0 或 某个 package user 的 uid) 和剩下来的在chroot前创建的文件(它们带着你主系统里的正常用户id). 作为普通用户编译还能保证不会因为失误而覆盖主系统里的文件。
在 chroot 前的命令不需要改变,但你需要加一些东西。第一个问题是我们在 chroot 中安装了 glibc 后马上就需要 find。最好的办法是在 chroot 前编译一个静态的 find:
./configure --prefix=$LFS/usr --disable-nls &&
make LDFLAGS=-static CPPFLAGS=-Dre_max_failures=re_max_f2 &&
make libexecdir=$LFS/usr/bin install
另一个问题是,在glibc安装前,某些程序比如chown,不能解释用户名称。幸运的是多数程序都接受数字形式的 UID 或 GID. 只有一个例外: su. 使用 package user 的基础竟然不能接受数字形式的 id:-|
那么我们在安装 glibc 前要怎样成为一个 package user 呢?你可能以为我写了一个脚本来代替它,你猜 ...
... 错了 :-) 我写了一个 C 程序来代替它.
碰巧 sh-utils 也包含了一个 su 程序,LFS里面没有用它。在 chroot 前静态编译安装了这个程序,但从来就没有用到(假设是标准的 LFS 安装), 在动态编译 sh-utils 时被替换,最后又被 shadow 中的 su 替换掉,这个才是最后的 LFS 系统里用到的 su 程序。所以你需要做的就是,在第五章编译 sh-utils 前,把 sh-utils 源码树下 src/su.c 用下面的内容替换。
注意如果你用普通用户编译第五章,你需要在"make install"后再运行"make install-root",要不然 sh-utils 就不会安装 su.
- -------- begin $LFS/usr/src/sh-utils/sh-utils-<version>/src/su.c ------------
- #include <stdio.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <ctype.h>
- #include <grp.h>
- #define NUMGIDS 1024
- int main(int argc,char* argv[])
- {
- char* Res;
- char Buffy[4096];
- uid_t tuid=-1,uid;
- gid_t gid;
- int i;
- FILE* File;
- char* command=NULL;
- char* shell;
- char* HOME;
- gid_t gid_list[NUMGIDS];
- ssize_t NumGids=0;
- if (argc>1)
- {
- if (strcmp(argv[1],"--help")==0)
- { fprintf(stdout,"There is no help!\n"); exit(0);}
- if (strcmp(argv[1],"--version")==0) {fprintf(stdout,"0.6\n"); exit(0); }
- }
- if ((argc==4) && (strcmp(argv[2],"-c")==0)) command=argv[3]; else
- if (argc!=2)
- {
- fprintf(stdout,"USAGE: su username|uid [-c command]\n");
- return 1;
- };
- i=0;
- while(isdigit(argv[1][i])) ++i;
- if (argv[1][i]==0) tuid=atol(argv[1]);
- File=fopen("/etc/passwd","rb");
- if (File==NULL) {perror("/etc/passwd"); return 1;};
-
- while(1)
- {
- errno=0;
- Res=fgets(Buffy,1024,File);
- if (Res==NULL) {
- if (errno!=0) perror("/etc/passwd");
- else fprintf(stderr,"su: User not found!\n");
- return 1;
- };
-
- Res=strtok(Buffy,":");
- if (Res==NULL) continue;
- strtok(NULL,":");
- uid=atol(strtok(NULL,":"));
- gid=atol(strtok(NULL,":"));
- strtok(NULL,":");
- HOME=strtok(NULL,":");
- shell=strtok(NULL,":");
- if (tuid==uid) {argv[1]=strdup(Buffy); break;}
- if (strcmp(argv[1],Buffy)==0) break;
- };
- HOME=strdup(HOME);
- shell=strdup(shell);
-
- File=fopen("/etc/group","rb");
- if (File==NULL) {perror("/etc/group"); return 1;};
-
- while(1)
- {
- ContinueReadingEtcGroup:
- errno=0;
- Res=fgets(Buffy,1024,File);
- if (Res==NULL) {
- if (errno!=0) {perror("/etc/group"); return 1;} else break;
- };
-
- Res=strtok(Buffy,":,\n");
- if (Res==NULL) continue;
- strtok(NULL,":,\n");
- gid_list[NumGids]=atol(strtok(NULL,":,\n"));
- Res=strtok(NULL,":,\n");
- while(Res!=NULL)
- {
- if (strcmp(Res,argv[1])==0)
- {
- ++NumGids;
- if (NumGids>=NUMGIDS) goto SetNewIdentity;
- else goto ContinueReadingEtcGroup;
- };
- Res=strtok(NULL,":,\n");
- };
- };
- SetNewIdentity:
- if (command==NULL) command=shell;
- setenv("HOME",HOME,1);
- setgroups(NumGids,gid_list);
- setgid(gid);
- setuid(uid);
- errno=0;
- i=system(command);
- if (((i<0) || (i==127)) && (errno!=0)) {perror("/bin/sh"); return 1;};
- return i;
- };
- -------- end $LFS/usr/src/sh-utils/sh-utils-<version>/src/su.c ------------
复制代码
这个 su 程序能接受用户名,也能接受数字形式的UID. 它使用 /etc/passwd 来进行独立的名称解释,所以在 glibc 安装前也能工作。
注意 sh-utils 安装 su 程序时会设置成 setuid 的。
如果你用普通用户来做第五章(为了安全,你应该这样), 即使是 root 来执行,su也不能工作。只要去掉 setuid 位就行了:
chmod u-s $LFS/bin/su
我们一进入 chroot 环境(这时是root身份),就能正常的使用 su. 注意你可以从 root 切换到某个 package user,但不能反着来。如果你想从 package user 用 su 切换到 root,就必须设置 su 为 setuid root(比如 chown root.root $LFS/bin/su && chmod u+s $LFS/bin/su). 确保你不会在其他人能接触到的系统里放这样的程序.
上面的 su 不检查密码,所以如果你让它setuid root,任何人都能成为 root,而无需密码! |
|