linux 权限源码级别.doc (alpha)

                   目标:解释open 返回 permission denied; todo:access有关

               动手比较篇:

#普通用户下:

strace  ls /etc >t1.file

#高级用户下:

strace ls /etc>t2.file 2>&1

 

      附注:其中2>&1由于starce 是默认fd输出到stderr,所以重定向到stdout

输入2个命令后,比较两个文本。

      下面是相关截图:

clip_image002      可见在调用open系统调用的时候,超级用户 返回正值, 但是 普通用户 返回 负数值。

这说明:权限的 system call是在 open的调用中 实现的。

                   源码级别分析:(alpha版本)

Todo:如何跟踪到 EACCES, PERMISSION DENIED的出现。

                        基础:eacces

Linux/include/asm-generic/errno-base.h


 

 13 #define ECHILD          10      /* No child processes */

 14 #define EAGAIN          11      /* Try again */

 15 #define ENOMEM          12      /* Out of memory */

 16 #define EACCES          13      /* Permission denied */


                        Open.c中返回eacces的函数:syscall_define3(确切是宏)

Todo:第一阶级: real uid/gid access

...

294 /*

295  * access() needs to use the real uid/gid, not the effective uid/gid.

296  * We do this by temporarily clearing all FS-related capabilities and

297  * switching the fsuid/fsgid around to the real ones.

298  */

299 SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)

300 {

301         const struct cred *old_cred;

302         struct cred *override_cred;

303         struct path path;

304         struct inode *inode;

305         int res;

306

307         if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */

308                 return -EINVAL;

309

310         override_cred = prepare_creds();

311         if (!override_cred)

312                 return -ENOMEM;

313

314         override_cred->fsuid = override_cred->uid;

315         override_cred->fsgid = override_cred->gid;

316

317         if (!issecure(SECURE_NO_SETUID_FIXUP)) {

318                 /* Clear the capabilities if we switch to a non-root user */

319                 if (override_cred->uid)

320                         cap_clear(override_cred->cap_effective);

321                 else

322                         override_cred->cap_effective =

323                                 override_cred->cap_permitted;

324         }

325

326         old_cred = override_creds(override_cred);

327

328         res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);

329         if (res)

330                 goto out;

331

332         inode = path.dentry->d_inode;

333

334         if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {

335                 /*

336                  * MAY_EXEC on regular files is denied if the fs is mounted

337                  * with the "noexec" flag.

338                  */

339                 res = -EACCES;

340                 if (path.mnt->mnt_flags & MNT_NOEXEC)

341                         goto out_path_release;

342         }

343

...

                        syscall_define3的定义

SYSCALL_DEFINE3

Defined as a preprocessor macro in:

·      include/linux/syscalls.h, line 193

看看下面是具体内容:

todo:第一阶级,下次syscall_definex

#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__

todo:上面的宏不止出现一次。看各自的注释。

fs/open.c:

·      line 299

·      line 487

·      line 552

·      line 596

·      line 615

·      line 915

原文地址:https://www.cnblogs.com/titer1/p/2014227.html