我发现使用pam库进行身份验证的应用程序在出错时失败:
Error writing /proc/self/loginuid: Operation not permitted
通过strace我发现写入/ proc / self / loginuid文件时失败。
进一步检查并向内核添加一些调试代码(下面的代码):
static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
struct inode * inode = file_inode(file);
uid_t loginuid;
kuid_t kloginuid;
int rv;
printk(KERN_DEBUG "proc_loginuid_write\n");
printk(KERN_DEBUG "a+++ %s\n", current->comm);
printk(KERN_DEBUG "b+++ %s\n", pid_task(proc_pid(inode), PIDTYPE_PID)->comm);
printk(KERN_DEBUG "+++2++ pid = %d\n", current->pid);
printk(KERN_DEBUG "+++3++ pid = %d\n", pid_task(proc_pid(inode), PIDTYPE_PID)->pid);
rcu_read_lock();
if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) {
rcu_read_unlock();
printk(KERN_ERR "proc_loginuid_write failed by permission!\n");
return -EPERM;
}
rcu_read_unlock();
if (*ppos != 0) {
/* No partial writes. */
return -EINVAL;
}
rv = kstrtou32_from_user(buf, count, 10, &loginuid);
if (rv < 0)
return rv;
/* is userspace tring to explicitly UNSET the loginuid? */
if (loginuid == AUDIT_UID_UNSET) {
kloginuid = INVALID_UID;
} else {
kloginuid = make_kuid(file->f_cred->user_ns, loginuid);
if (!uid_valid(kloginuid))
return -EINVAL;
}
rv = audit_set_loginuid(kloginuid);
if (rv < 0)
return rv;
return count;
}
在dmesg中显示:
[ 30.672242] proc_loginuid_write
[ 30.672249] a+++ testapp
[ 30.672251] b+++ testapp
[ 30.672254] +++2++ pid = 2920
[ 30.672257] +++3++ pid = 2451
[ 30.672259] proc_loginuid_write failed by permission!
名称testapp是故意更改名称。所以看起来文件/ proc / self / loginuid是父文件创建的文件,它由子线程读取。
我在内核3.14和4.9上测试了相同的代码,在3.14内核上运行了它,在内核4.9上它不起作用。为什么呢?
答案 0 :(得分:0)
我找到了问题的解决方案。
旧内核3.14 已关闭配置中的选项 CONFIG_AUDITSYSCALL 。所以没有文件/ proc / self / loginuid和pam模块在没有这样的文件时根本不在乎。
CONFIG_AUDIT = y 会自动选择较新的内核4.9 选项。 最简单的解决方案是关闭 CONFIG_AUDIT 选项,但是为什么在内核演化过程中 CONFIG_AUDITSYSCALL 成为一个不可控制的选项是其他问题的问题。
谢谢!