|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
写学习日记,这是学习历程的见证,同时我坚持认为是增强学习信念的法宝。以上是我学习Linux的心得体会,希望对大家的学习有所帮助,由于水平有限,本文难免有所欠缺,望请指正。
谢谢收躲http://www.qqread.com/linux/2006/06/y786123061.html
4、回护主要历程
历程是操纵体系的静态出口。内核里有两个特别历程,历程ID0(swapd)和历程ID1(init)。Init历程是在体系启动的时分一切历程的父历程。
1、不成杀逝世的历程。
就象你能够看到是不是有人要夺得root特权一样,我们能够很简单的杀逝世那些该内核发送出格旌旗灯号的历程。为了杀逝世一个历程,你必需失掉历程的ID,然后用kill命令来杀逝世它。
体系杀逝世历程的挪用是kill,是在内核里的sys_kill()命令里的挪用。
让我们看看LIDS的回护代码
在/usr/src/linux/kernel/signal.c里
asmlinkageint
sys_kill(intpid,intsig)
{
structsiginfoinfo;
#ifdefCONFIG_LIDS_INIT_CHILDREN_LOCKpid_tthis_pid;
inti;
#ifdefCONFIG_LIDS_ALLOW_KILL_INIT_CHILDREN
if(!(current->flags&PF_KILLINITC))
#endif
if(lids_load&&lids_local_load&&LIDS_FISSET(lids_flags,LIDS_FLAGS_LOCK_INIT_CHILDREN)){
this_pid=pid>0?pid:-pid;
for(i=0;i
if(this_pid==lids_protected_pid){
lids_security_alert("Trytokillpid=%d,sig=%dn",pid,sig);
return-EPERM;
}
}
}
#endif
...
}
你能够在内核里看到两个标签,,CONFIG_LIDS_INIT_CHILDREN_LOCK和CONFIG_LIDS_ALLOW_KILL_INIT_CHILDREN.
在CONFIG_LIDS_INIT_CHILDREN_LOCK的开启形态,LIDS能回护初使的运转程序。如,假如你在体系里运转inetd程序,你能够在埋没内核前运转它,然后,你还能够杀逝世它。可是一些人假如telnet到你的呆板,inetd就会制造子历程来为用户服务,这个子历程不会被LIDS回护,由于用户在任什么时候候加入和杀逝世程序。
2、埋没历程
别的一个回护历程的办法就是埋没历程。当一个黑客危急你的体系。他会上岸,然后会看看有无一些已知的历程在监督它。然后他就杀逝世它。假如你埋没了这个功效的历程,黑客就不会晓得历程的一切情形而且你能够纪录他在你体系上做的任何事变。
怎样埋没历程
为了埋没历程,你必需在设置内核的时分供应一个完整的路径名。
当内核启动的时分,LIDS会会见文件结点到一个叫proc_to_hide[]的布局里。
在include/linux/sched.h里
#ifdefCONFIG_LIDS_HIDE_PROC
#definePF_HIDDEN0x04000000/*Hiddenprocess*/
#endif
/*infs/lids.c*/
#ifdefCONFIG_LIDS_HIDE_PROC
structallowed_inoproc_to_hide[LIDS_MAX_ALLOWED];
intlast_hide=0;
#endif
....
/*infs/lids.c,init_vfs_security(),
fillupthehiddenprocessinproc_to_hide[]
*/
#ifdefCONFIG_LIDS_HIDE_PROC
lids_fill_table(proc_to_hide,&last_hide,LIDS_MAX_ALLOWED,CONFIG_LIDS_HIDDEN_PROC_PATH);
#endif
PF_HIDDEN是不是用户能够用显现历程的命令(如“psCa”)来显现和反省历程,假如一个历程被LIDS埋没,当他实行的时分,历程就会失掉一个PF_HIDDEN的属性。然后,当体系输入体系历程信息到用户的时分,它就会能够反省以后输入历程是不是有PF_HIDDEN标记。假如发明了,它就不会输入这个历程的信息。
在infs/exec.c
intdo_execve(char*filename,char**argv,char**envp,structpt_regs*regs)
{
...
if(retval>=0){
#ifdefCONFIG_LIDS_HIDE_PROC
if(lids_search_proc_to_hide(dentry->d_inode))
current->flags|=PF_HIDDEN;
...
由于每个linux的历程都有一个在/proc文件体系的出口,我们为了埋没历程也必要修正proc的文件出口。
在fs/proc/root.c
staticstructdentry*proc_root_lookup(structinode*dir,structdentry*dentry)
{
...
inode=NULL;
#ifdefCONFIG_LIDS_HIDE_PROC
if(pid&&p&&(!((p->flags&PF_HIDDEN)&&lids_load&&lids_local_load))){
#else
if(pid&&p){
#endif
unsignedlongino=(pid>>16)+PROC_PID_INO;
inode=proc_get_inode(dir->i_sb,ino,&proc_pid);
if(!inode)
returnERR_PTR(-EINVAL);
inode->i_flags|=S_IMMUTABLE;
}
...
}
然后假如历程被PF_HIDDEN标志,它就不会在proc文件体系里显现。
5、密封内核
我们必要在体系启动的时分做一些需要的操纵,可是我们也必要在体系运转的时分回护它们。
比方,我们必要象内核里拔出一些必要的模块,可是我们不但愿在体系运转的时分拔出任何模块,由于那样会非常伤害。怎样办理这个成绩呢?这里就有一些密封的办法。我们能够在体系启动的时分做我们任何想做的事变,然后我们就密封内核。然后,我们就不克不及做那些之前在没有密封的时分能够做的事变。用密封的办法,我们能够用模块来办理成绩,我们能够在密封前向内核里拔出我们想要的模块,在密封后我们就不成以在内核里拔出或是删除任何模块。
1、用LIDS密封内核
为了密封内核,我们能够用上面的LIDS命令
#lidsadmCI---CAP_xxx….
它们能够放到剧本里让体系启动的时分就实行它。详细你们能够看我之前在linuxbyte和chinabyte宣布的文章。LIDS是经由过程/proc/sys/lids/locks和内核通信的。
当你密封了内核,lidsadm是挪用lidsadm.c的lids_init()的挪用。
#defineLIDS_LOCKS"/proc/sys/lids/locks"
......
voidlids_init(intoptind,intargc,char*argv[])
{
......
if((fd=open(LIDS_LOCKS,O_RDWR))==-1){
perror("open");
exit_error(2,"canopen"LIDS_LOCKS);
}
if(read(fd,&locks,sizeof(lids_locks_t))==-1){
perror("read");
exit_error(2,"canread"LIDS_LOCKS);
}
lids_set_caps(optind,argc,argv,&locks);
locks.magic1=LIDS_MAGIC_1;
.........
if(write(fd,&locks,sizeof(lids_locks_t))==-1){
perror("write");
exit_error(2,"canwrite"LIDS_LOCKS);
}
.....
}
这个体系挪用在LIDS_LOCKS天生新的变量loks,内核会经由过程lids_proc_locks_sysctl()命令来读取它。Lids_proc_locks_sysctl也会从用户区完整反省并读取它,然后改动密封的变量lids_first_time为0。
让我们看看lids_proc_locks_sysctl().这个函数会在用户读写/proc/sys/lids/locks的时分挪用。
intlids_proc_locks_sysctl(ctl_table*table,intwrite,structfile*filp,
void*buffer,size_t*lenp,intconv,intop)
{
...........
/*first:checktheterminalandtheprogramwhichaccessthesysctl*/
#ifndefCONFIG_LIDS_REMOTE_SWITCH
if(current->tty&&(current->tty->driver.type!=2)){
lids_security_alert("Tryto%slockssysctl(unauthorizedterminal)",
write?"write":"read");
return-EPERM;
}
#endif
........
/*second:checkwetheritisnotatimeoutperiodaftertwomanyfailedattempts*/
.......
if(write){
/*Third:checkwhatissubmitted(size,magics,passwd)*/
if(*lenp!=sizeof(lids_locks_t)){
lids_security_alert("Trytofeedlockssysctlwithgarbage");
return-EINVAL;
}
if(copy_from_user(&locks,buffer,sizeof(lids_locks_t)))
return-EFAULT;
.......
if((lids_first_time)&&(!locks.passwd[0])){
.........
number_failed=0;
if(lids_process_flags(locks.flags)){
cap_bset=locks.cap_bset;
lids_security_alert("Changed:cap_bset=0x%xlids_flags=0x%x",cap_t(cap_bset),lids_flags);
}
Changeflaghere..-->lids_first_time=0;
.....
}
下面的函数会在密封内核或是改动内核平安级其余时分事情。变量lids_first_time是一个标明以后密封形态的的一个标记。当改动了必要的使能位,这个标记就会置1标明以后的形态是“密封后“。
密封内核有两个义务,起首,改动使能位,然后,改动lids_first_time标记为1。在密封后,体系就不同意改动它们了,除非你用lidsadm和暗码。
2、在密封前回护程序
由于在密封前的形态是伤害的,我们必需晓得在密封前那些运转的程序是LIDS来回护的。为何呢?由于密封后我们就不克不及改动它们了。假如文件没有被回护,一些人就能够改动他们然后从头启动,这些程序大概对体系十分伤害。让我们来看看在没有密封前一个运转的非回护程序的代码。
intdo_execve(char*filename,char**argv,char**envp,structpt_regs*regs)
{
..........
#ifdefCONFIG_LIDS_SA_EXEC_UP
if(lids_first_time&&lids_load){
if(!lids_check_base(dentry,LIDS_READONLY))
#ifdefCONFIG_LIDS_NO_EXEC_UP
lids_security_alert("Trytoexecunprotectedprogram%sbeforesealingLIDS",filename);
if(dentry)
dput(dentry);
return-EPERM;
#else
lids_security_alert("Execedunprotectedprogram%sbeforesealingLIDS",filename);
#endif
}
}
#endif
......
}
你会看到当LIDS回护体系开启(lids_load==1)和以后体系没有密封(lids_firest_time为1)的时分,内核就会反省以后程序是不是在LIDS的lids_check_base()回护下。假如没有被回护,它就会启动报警信息。
6、LIDS与Capability
1、Capability是一套来标明一个历程能够做为何的位标记。在LIDS,我们能够用capability的限定来限定一切的历程。
在/include/linux/capability.h
typedefstruct__user_cap_header_struct{
__u32version;
intpid;
}*cap_user_header_t;
typedefstruct__user_cap_data_struct{
__u32effective;
__u32permitted;
__u32inheritable;
}*cap_user_data_t;
#ifdef__KERNEL__
/*#defineSTRICT_CAP_T_TYPECHE
#ifdefSTRICT_CAP_T_TYPECHECKS
typedefstructkernel_cap_struct{
__u32cap;
}kernel_cap_t;
#else
typedef__u32kernel_cap_t;
#endif
kernel_cap_tcap_bset=CAP_FULL_SET;
在kernel_ap_t的每位都代表一个允许。Cap_bset是capability集的次要部分。它们的值能够经由过程改动/proc/sys/kernel/cap-bound来改动。
看看下面的文件,你就会发明一些成绩。
/*ininclude/linux/capability.h*/
/*Inasystemwiththe[_POSIX_CHOWN_RESTRICTED]optiondefined,this
overridestherestrictionofchangingfileownershipandgroup
ownership.*/
#defineCAP_CHOWN0
/*OverrideallDACaccess,includingACLexecuteaccessif
[_POSIX_ACL]isdefined.ExcludingDACaccesscoveredby
CAP_LINUX_IMMUTABLE.*/
#defineCAP_DAC_OVERRIDE1
/*OverridesallDACrestrictionsregardingreadandsearchonfiles
anddirectories,includingACLrestrictionsif[_POSIX_ACL]is
defined.ExcludingDACaccesscoveredbyCAP_LINUX_IMMUTABLE.*/
#defineCAP_DAC_READ_SEARCH2
.........
每个义务(历程)在布局task_struct界说了三个成员:cap_effective,cap_inheritable,cap_permitted.我们已有了一个用来标明基础capability的变量cap_bset。它们会检测这个体系并断定那种capability用来把持体系。
在内核完成的年夜部分体系挪用会挪用函数capable()(在kernel/sched.c)。然后会挪用cap_raised()(在/include/linux/capability.h)。以下:
#ifdefCONFIG_LIDS_ALLO
12下一页
常用的linux命令,尤其是一些能帮你提高开发效率的命令,(eg:grep,awk,sed,split等); |
|