目标:解释open 返回 permission denied; todo:access有关
动手比较篇:
#普通用户下:
strace ls /etc >t1.file
#高级用户下:
strace ls /etc>t2.file 2>&1
附注:其中2>&1由于starce 是默认fd输出到stderr,所以重定向到stdout
输入2个命令后,比较两个文本。
下面是相关截图:
可见在调用open系统调用的时候,超级用户 返回正值, 但是 普通用户 返回 负数值。
这说明:权限的 在system call是在 open的调用中 实现的。
源码级别分析:(alpha版本)
Todo:如何跟踪到 : EACCES, PERMISSION DENIED的出现。
基础:eacces
13 #define ECHILD 10 /* No child processes */
14 #define EAGAIN 11 /* Try again */
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;
307 if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
310 override_cred = prepare_creds();
311 if (!override_cred)
314 override_cred->fsuid = override_cred->uid;
315 override_cred->fsgid = override_cred->gid;
317 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
318 /* Clear the capabilities if we switch to a non-root user */
320 cap_clear(override_cred->cap_effective);
321 else
322 override_cred->cap_effective =
323 override_cred->cap_permitted;
324 }
326 old_cred = override_creds(override_cred);
328 res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
332 inode = path.dentry->d_inode;
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 */
340 if (path.mnt->mnt_flags & MNT_NOEXEC)
341 goto out_path_release;
342 }
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