Detect the Shell File

Một phần của tài liệu The art of linux kernel design (Trang 216 - 221)

4. Creation and Execution of Process 2 165

4.3 Load the Shell Program

4.3.2 Detect the Shell File

4.3.2.1 Detect the Attribute of the i node

The do_execve() function calls the namei() function to get the i node of the shell first, the procedure of get inode is similar with the process of get inode in Section 4.1.1, and the system checks the attribute of the i node to determine whether the shell program can be loaded. The code is as follows:

int do_execve(unsigned long * eip,long tmp,char * filename, char ** argv, char ** envp)

{

struct m_inode * inode;

struct buffer_head * bh;

struct exec ex;

unsigned long page[MAX_ARG_PAGES];

int i,argc,envc;

int e_uid, e_gid;

int retval;

int sh_bang = 0;

unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;

ROM BIOS and VGA

f_mode f_flags f_count f_inode f_pos Kernel

Enable interrupt

0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF

Kernel code area Kernel data area

i node_table[32] file_table[64]

The i node pointing to /etc/rc Process status

Process 0 Process 1 Process 2

Interruptible Interruptible Ready

Current process

Figure 4.19 Open/etc/rc.

The procedure on how to get the i node is shown in Figure 4.20.

The procedure on how to detect the i node is shown in Figure 4.21.

By detecting the attribute of the i node of the shell file, we know that process 2 can execute the program in this context.

4.3.2.2 Test File Header’s Attributes

Through the information of the device id and block id provided by the i node, the system will load the file header to the buffer and get its information. The code is as follows:

if ((0xffff & eip[1]) !=0x000f //checks whether the kernel calls //do_execve() by checking privilege level

panic(“execve called from supervisor mode”);//if yes, the //kernel will crash, obviously, it is not true in this case.

for (i=0 ; i<MAX_ARG_PAGES ; i++)

page[i]=0; //clear the page pointer management table, which //used to parameter and environmental variables

if (!(inode = namei(filename)))//get the inode of shell program file return -ENOENT;

argc = count(argv);//count the parameters

envc = count(envp);//count the environment variables restart_interp:

if (!S_ISREG(inode->i_mode)) { /* must be regular file */

retval = -EACCES;

goto exec_error2;

}

i = inode->i_mode;//check process 2 through checking uid and gid in inode e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;//whether has the

//authority to execute shell program e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;

if (current->euid == inode->i_uid)

i >>= 6; //adjust the permission bits in //inode by analyzing the owner //relationship between file and //current process

else if (current->egid == inode->i_gid) i >>= 3;

if (!(i & 1) && //exit the loading work, if user has no //permission to execute shell program

!((inode->i_mode & 0111) && suser())) { retval = -ENOEXEC;

goto exec_error2;

} }

……

int do_execve(unsigned long * eip,long tmp,char * filename, char ** argv, char ** envp)/*system_call.s*/

{

……

if (!(i & 1) &&//If user don’t have permission to perform the //program,the shell will exit the loading work

!((inode->i_mode & 0111) && suser())) { retval = -ENOEXEC;

goto exec_error2;

}

if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {

//Through the i_nodes to make sure the device id and block //id(i_zone[0]) of shell file and get the file header

retval = -EACCES;

goto exec_error2;

}

ex = *((struct exec *) bh->b_data); //Get the information of file header //

from buffer block

if ((bh->b_data[0] == ‘#’) && (bh->b_data[1] == ‘!’) && (!sh_bang)) {

……

brelse(bh);

if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||

ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||

inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) { retval = -ENOEXEC;

goto exec_error2;

}

if (N_TXTOFF(ex) != BLOCK_SIZE) {

printk(“%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.”, filename);

retval = -ENOEXEC;

goto exec_error2;

}

if (!sh_bang) {

p = copy_strings(envc,envp,page,p,0);

p = copy_strings(argc,argv,page,p,0);

if (!p) {

retval = -ENOMEM;

goto exec_error2;

} }

}

……

Kernel

Enable interrupt

0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF

Kernel code area Kernel data area

i node_table[32]

Buffer block

Get i node Process status

Process 0 Process 1 Process 2

Interruptible Interruptible Ready

Current process

ROM BIOS and VGA

Figure 4.20 Get the i node of shell.

The procedure of obtaining the file header is shown in Figures 4.22 and 4.23.

The system will check the information of the file header to confirm the content of the shell file and judge whether it is fit for the rule of loading. The code is as follows:

int do_execve(unsigned long * eip,long tmp,char * filename, char ** argv, char ** envp)/*system_call.s*/

{

……

if (!(i & 1) &&//If user don’t have permission to perform the //program,the shell will exit the loading work

!((inode->i_mode & 0111) && suser())) { retval = -ENOEXEC;

goto exec_error2;

}

if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {

//Through the i_nodes to make sure the device id and block //id(i_zone[0]) of shell file and get the file header

retval = -EACCES;

goto exec_error2;

}

ex = *((struct exec *) bh->b_data);//Get the information of file header //from buffer block

if ((bh->b_data[0] == ‘#’) && (bh->b_data[1] = = ‘!’) && (!sh_bang)) { //Test file header, learned that shell file is not script file,so the //contents of if don’t execute

……

brelse(bh);

Kernel

Enable interrupt

0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF

Kernel code area Kernel data area

i node_table[32]

Process status

Process 0 Process 1 Process 2

Interruptible Interruptible Ready

Current process

ROM BIOS and VGA

Figure 4.21 Detect the i node of shell.

Figure 4.23 shows an incidence of testing the file header.

After checking the header attributes of the shell file, we find that the program in the shell file is ready to run.

if (N_MAGIC(ex) ! = ZMAGIC || ex.a_trsize || ex.a_drsize ||

ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||

inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) { //Test the information of file header to make sure the content of shell //file and judge it whether fit for the rule of loading

retval = -ENOEXEC;

goto exec_error2;

}

if (N_TXTOFF(ex) ! = BLOCK_SIZE) {

//If the file header size is not equal to 1024, the program might not //be executed

printk(“%s: N_TXTOFF ! = BLOCK_SIZE. See a.out.h.”, filename);

retval = -ENOEXEC;

goto exec_error2;

}

if (!sh_bang) {

p = copy_strings(envc,envp,page,p,0);

p = copy_strings(argc,argv,page,p,0);

if (!p) {

retval = -ENOMEM;

goto exec_error2;

} } }

……

ROM BIOS

and VGA Enable

interrupt

0x00000 0x9FFFF 0xFFFFF 0x3FFFFF 0x5FFFFF 0xFFFFFF

Read the shell file header into buffer Kernel

Process status

Process 0 Process 1 Process 2

Interruptible Interruptible Ready

Current process

\0\0\0

Figure 4.22 Read the shell file header into the buffer.

Một phần của tài liệu The art of linux kernel design (Trang 216 - 221)

Tải bản đầy đủ (PDF)

(524 trang)