は私が認証するために、PAMライブラリを使用して、そのアプリケーションがエラーに失敗した:straceのことでなぜ、pam_loginuidモジュールが-EPERMを使って/ proc/self/loginuidへの書き込みに失敗するのですか?
Error writing /proc/self/loginuid: Operation not permitted
は、私は/ procの/自己/ 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では動作しません。どうして?
なぜカーネル進化の過程でCONFIG_AUDITSYSCALLが制御不能なオプションになったのか他の質問のための問題です。 - 通常、新しいカーネル機能は、 "有用性"が欠点よりはるかに大きくてもオプションで、デフォルト。これは、機能の実装が正しくない可能性があるためです。しばらくすると、機能が安定した後、デフォルトが「有効」に変更される可能性があります。 ** AUDITSYSCALL **の設定は、この戦略に正確に従います。 – Tsyvarev