From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.openvz.org (mail.openvz.org [69.168.225.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id EF4AF8146A for ; Mon, 9 Nov 2026 19:37:38 +0000 (UTC) Received: from mail.openvz.org (localhost [127.0.0.1]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6A9JaOl8003212; Mon, 9 Nov 2026 22:36:25 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A9JaOl8003212 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="dmd1ECiX" Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 6A9Ja9Zf003166 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Mon, 9 Nov 2026 22:36:10 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 6A9Ja9Zf003166 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-4a16dc2323cso9986355e9.3 for ; Mon, 09 Nov 2026 11:36:09 -0800 (PST) X-Forwarded-Encrypted: i=2; AL+hErGnOgTZocoZWs9JWItm4IvMJhECoxnli/aZ4EyI6GEIKk1esHuuF35s54/mPl77hjhl6hWq6A==@openvz.org X-Gm-Message-State: APuU4Z+8EkfzorvjhRrtha5ooAzd3+uHFoRrWdDtb3xbZlbBqF1dEktY GQ4VIv4sNOifiwaDPq6WKSJRXLiJ2rgkmXK7LonVG0UNaxeUYx8s0GqsYR7rhJOF/rlhYfshTXr bcrRoev+qLZ9gHOfxbsTAMmeRwZ2KS616Y2ioaEJvKqGvLpADETWb3A== X-Gm-Gg: AYBFou14jKtFD4rkdspcJVewadZp9M2si9cl38ZPYkr6Gtk1Xyvp10Nt0zwUJGJW29h q66Yvcx98qbwLNueWvcv2v+JbJqtMGutg54lqRrG+H1h7avN4t6fKR/Ixn1gw3cma4dOeFI22hF BpxJvUkvGnjjAs3fbolVbKPGnvLZdj1svMedBBO8oFeuwa56e70pHV2CYpAeNhvIWyi3s5hWbRu tVk1oCKZAd2Wq+k0KOJCVoEsB1YxbtlOAfeyTPEIWbPsw2L78OW54KgAR2RWaa5DyHpN5avMmd+ 1aeDHEuAAKAp3sra1/5riSHWYkd5Ijr5Lr9+ZHFq/LiV+mIoUfjIC/XW/x6ydg55OW6ur359RhK CTbKL4wb5yykQzBN7wgXwsfMqbWf/ X-Received: by 2002:a05:600c:3b98:b0:4a7:462c:6b9e with SMTP id 5b1f17b1804b1-4ba02351506mr4300295e9.32.1794252969619; Mon, 09 Nov 2026 11:36:09 -0800 (PST) X-Received: by 2002:a05:600c:3b98:b0:4a7:462c:6b9e with SMTP id 5b1f17b1804b1-4ba02351506mr4299835e9.32.1794252969022; Mon, 09 Nov 2026 11:36:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1794252969; cv=none; d=google.com; s=arc-20260327; b=hvBnwptzE1u7gqtpsi/Jjit6NRiJgy2YKPzK0jwDBlAIqF22+ntBnioxtt4oIB9yvo LCI8yRbwppM5ZQkIFigPyfL6mDvChDH92X+aD1ImDCtLaOaQFLuLYBlzp7ghoP6DFHiZ knKdqefeqNDNXgRPXuuWkGplQrDEOokQAKq/p49KaY9J2OlcKZqwaWPr7TWSWXlglFt0 LOHe25fdZXHBq2txlmcTdr9TQ2JOPu0o+FMODNRanyZj7K9hfAEirBtyvjB+M2CYbF+X djHKj4mFcUQLVj8Uh2DSV3G2Yk9uFCxmDS5hUlV0oNx2+/SxjPUm6T3y7BzHO3SOt/XE oZxQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:dkim-signature; bh=U7z9aVotKxI/eY9AQgiOY2X5PmWMnSZSlnCujTR+pq0=; fh=5hQRK+XZF8m8FADH0g5yAiDkSoTAVGTSxnnvVVATGZQ=; b=MxWPGbhy6My92OtibOtTOGJBQ4SLSQPZu7pBgO/zbAorzLOu824rjX2fcK3/tSKyOO JDIPcxIWRjpvS9Dtatbf67K69Brh6XQm/zJipOCKwKa7vEViqmzDxlOHC3IDjpFUDPWC RBB3ySLV8y6l3zYF9nAl3N8vMkObRn7HxIMbxAnLvt8O6mkbEIJR6k1WsVazQKxdWDtG CsChwsDHgkxyBZyMP5FOF4D9BfTpapDeRVNYDegeKIePvIC6T6v5axpRoJMoS7NCrPj+ ptqgTeawsl/3/ErdcPnBZoYKiYcZjAkaHU2IU8nzGN391/+OLonkMSZGtZ3iMkAkmgGs LLBw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=dmd1ECiX; spf=pass (google.com: domain of vladimir.riabchun@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=vladimir.riabchun@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com Received: from relay.virtuozzo.com (relay.virtuozzo.com. [130.117.225.111]) by mx.google.com with ESMTPS id 5b1f17b1804b1-4ba0203a909si8196695e9.4.2026.11.09.11.36.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Nov 2026 11:36:09 -0800 (PST) Received-SPF: pass (google.com: domain of vladimir.riabchun@virtuozzo.com designates 130.117.225.111 as permitted sender) client-ip=130.117.225.111; Authentication-Results: mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=dmd1ECiX; spf=pass (google.com: domain of vladimir.riabchun@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=vladimir.riabchun@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=Message-Id:Content-Type:MIME-Version:Subject:Date :From; bh=U7z9aVotKxI/eY9AQgiOY2X5PmWMnSZSlnCujTR+pq0=; b=dmd1ECiXcL9ZR5h5zJx 6evIJ7g8aFwncOQzzrtl1dlvMLiINOoB4KlmtK5r+EBpejYaHLREif6y+E1pdRWi1yaz9oUAsaRRC vNUGUIi2do9RPKgqRqj8ff4JbuhEhAkMpOQgvXrY5qoh9WVMqjhII55VgWhhW0iOBssZauUCTGcQz hjLopyC9KiE6x3n0nk19/NqemCBvs+5zkIsMNKBLO1CrZtRn2e4U/wbktFes6ro7AB+SGK1pP5E6D Lg9cLqMlU6aeZZo7NgSjqE+yRYkCcr+mgGrIYijlYsDF0qDwCFrizJopYHwODlMD+/TbJuIN860o0 IcveGHBdG9ATnBA==; Received: from ch-demo-asa.virtuozzo.com ([130.117.225.8] helo=192.168.1.87) by relay.virtuozzo.com with esmtps (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1xQV5v-00CGp3-2u; Mon, 09 Nov 2026 20:36:00 +0100 From: Vladimir Riabchun Date: Mon, 09 Nov 2026 20:36:03 +0100 MIME-Version: 1.0 Message-Id: <20261109-ovl-use-orig-ve-v4-5-88e65484dc5b@virtuozzo.com> References: <20261109-ovl-use-orig-ve-v4-0-88e65484dc5b@virtuozzo.com> In-Reply-To: <20261109-ovl-use-orig-ve-v4-0-88e65484dc5b@virtuozzo.com> To: ptikhomirov@virtuozzo.com, Konstantin Khorenko X-Mailer: b4 0.16.0 X-OZ-Fwd: true Cc: devel@openvz.org Subject: [Devel] [PATCH hci-8.1 v4 5/5] ve/overlayfs: Override VE together with creds X-BeenThere: devel@openvz.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: OpenVZ development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: devel-bounces@openvz.org Errors-To: devel-bounces@openvz.org Host users might want to access overlayfs owned by CT. In such case ve_capable checks will fail - they will perform VE cred checks against host user_ns. Modify ovl_override_creds so that it returns both old cred and old VE. This will also protect us from future rebase issues - all new users of old_cred and ovl_override_creds will fail with compilation error. This fixes an observed crash in overlayfs when checkpointing a container with a docker running inside: [ 2300.870181] BUG: kernel NULL pointer dereference, address: 0000000000000005 [ 2300.871537] #PF: supervisor read access in kernel mode [ 2300.872577] #PF: error_code(0x0000) - not-present page [ 2300.873595] PGD 800000010a18f067 P4D 800000010a18f067 PUD 10730c067 PMD 0 [ 2300.874900] Oops: Oops: 0000 [#1] SMP PTI [ 2300.875742] CPU: 1 UID: 0 PID: 5419 Comm: criu ve: 0 Kdump: loaded Not tainted 6.12.0-211.39.1.16.6.vz10.x86_64 #1 16.6 PREEMPT(voluntary) [ 2300.878057] Hardware name: Acronis OpenStack Compute/Virtuozzo, BIOS 1.16.1-1.vz9.2 04/01/2014 [ 2300.879684] RIP: 0010:ovl_get_index_name_fh+0x18/0x70 [overlay] [ 2300.880859] Code: ... [ 2300.884128] RSP: 0018:ffffd32582e0f7c0 EFLAGS: 00010246 [ 2300.885153] RAX: ... [ 2300.895807] Call Trace: [ 2300.896397] [ 2300.903298] ? ovl_get_index_name_fh+0x18/0x70 [overlay] [ 2300.904435] ovl_create_index+0x82/0x260 [overlay] [ 2300.905406] ovl_copy_up_workdir+0x30a/0x330 [overlay] [ 2300.906427] ovl_do_copy_up+0x10d/0x2e0 [overlay] [ 2300.907387] ovl_copy_up_one+0x456/0x720 [overlay] [ 2300.910736] ovl_copy_up_flags+0x81/0x110 [overlay] [ 2300.911740] ovl_create_object+0x51/0x130 [overlay] [ 2300.912719] vfs_mkdir+0x194/0x250 [ 2300.913470] do_mkdirat+0x14c/0x180 [ 2300.914223] __x64_sys_mkdir+0x46/0x70 [ 2300.915019] do_syscall_64+0x7d/0x160 [ 2300.922814] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 2300.923823] RIP: 0033:0x7f5a2f8de3eb Overlayfs was created inside CT, so ovl_fill_super stored in-container credentials to ofs->creator_cred. Those creds were later used in ovl_override_creds to temporarily swich creds and perform checks using them. One of these checks happened in ovl_get_origin_fh/ovl_can_decode_fh. On fs creation this check passed because we had container VE and container creds, so overlayfs thought that we support file handles (ovl_can_decode_fh call in ovl_make_workdir). When we tried to do something with the overlayfs from host VE, ve_capable check was performed with credentials from CT and with host VE. ovl_get_origin_fh returned unexpected NULL and all exploded. Stroing ve_capable check result on creation is a possible fix, but it just masks the problem. We have other paths from overlay to ve_capable checks: ovl_fileattr_set ovl_override_creds ovl_real_fileattr_set vfs_fileattr_set fileattr_set_prepare ve_capable And storing capability check result will make rebase dangerous - we would have to track new added code - not funny. https://virtuozzo.atlassian.net/browse/VSTOR-142405 Signed-off-by: Vladimir Riabchun --- fs/overlayfs/copy_up.c | 6 ++-- fs/overlayfs/dir.c | 59 ++++++++++++++++++------------ fs/overlayfs/file.c | 65 +++++++++++++++++++-------------- fs/overlayfs/inode.c | 94 +++++++++++++++++++++++++++++++----------------- fs/overlayfs/namei.c | 39 +++++++++++++------- fs/overlayfs/overlayfs.h | 9 ++++- fs/overlayfs/readdir.c | 36 ++++++++++++------- fs/overlayfs/util.c | 41 ++++++++++++++++----- fs/overlayfs/xattrs.c | 35 +++++++++++------- 9 files changed, 252 insertions(+), 132 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 4388004a319d..f478d1b51af9 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -1215,7 +1215,7 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, static int ovl_copy_up_flags(struct dentry *dentry, int flags) { int err = 0; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; bool disconnected = (dentry->d_flags & DCACHE_DISCONNECTED); /* @@ -1235,7 +1235,7 @@ static int ovl_copy_up_flags(struct dentry *dentry, int flags) if (err) return err; - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); while (!err) { struct dentry *next; struct dentry *parent = NULL; @@ -1260,7 +1260,7 @@ static int ovl_copy_up_flags(struct dentry *dentry, int flags) dput(parent); dput(next); } - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return err; } diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 1c8009bf194b..23897fabe9d5 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -554,7 +554,7 @@ static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode, } static int ovl_setup_cred_for_create(struct dentry *dentry, struct inode *inode, - umode_t mode, const struct cred *old_cred) + umode_t mode, const struct ovl_creds_desc *old_cred) { int err; struct cred *override_cred; @@ -566,7 +566,7 @@ static int ovl_setup_cred_for_create(struct dentry *dentry, struct inode *inode, override_cred->fsuid = inode->i_uid; override_cred->fsgid = inode->i_gid; err = security_dentry_create_files_as(dentry, mode, &dentry->d_name, - old_cred, override_cred); + old_cred->cred, override_cred); if (err) { put_cred(override_cred); return err; @@ -581,10 +581,12 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, struct ovl_cattr *attr, bool origin) { int err; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; struct dentry *parent = dentry->d_parent; - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + return err; /* * When linking a file with copy up origin into a new parent, mark the @@ -610,7 +612,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, * create a new inode, so just use the ovl mounter's * fs{u,g}id. */ - err = ovl_setup_cred_for_create(dentry, inode, attr->mode, old_cred); + err = ovl_setup_cred_for_create(dentry, inode, attr->mode, &old_cred); if (err) goto out_revert_creds; } @@ -621,7 +623,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, err = ovl_create_over_whiteout(dentry, inode, attr); out_revert_creds: - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return err; } @@ -697,12 +699,15 @@ static int ovl_symlink(struct mnt_idmap *idmap, struct inode *dir, static int ovl_set_link_redirect(struct dentry *dentry) { - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int err; - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + return err; + err = ovl_set_redirect(dentry, false); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return err; } @@ -888,7 +893,7 @@ static void ovl_drop_nlink(struct dentry *dentry) static int ovl_do_remove(struct dentry *dentry, bool is_dir) { int err; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; bool lower_positive = ovl_lower_positive(dentry); LIST_HEAD(list); @@ -907,12 +912,15 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) if (err) goto out; - old_cred = ovl_override_creds(dentry->d_sb); - if (!lower_positive) - err = ovl_remove_upper(dentry, is_dir, &list); - else - err = ovl_remove_and_whiteout(dentry, &list); - revert_creds(old_cred); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (!err) { + if (!lower_positive) + err = ovl_remove_upper(dentry, is_dir, &list); + else + err = ovl_remove_and_whiteout(dentry, &list); + ovl_revert_creds(&old_cred); + } + if (!err) { if (is_dir) clear_nlink(dentry->d_inode); @@ -1095,7 +1103,7 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir, bool new_is_dir = d_is_dir(new); bool samedir = olddir == newdir; struct dentry *opaquedir = NULL; - const struct cred *old_cred = NULL; + struct ovl_creds_desc old_cred = {}; struct ovl_fs *ofs = OVL_FS(old->d_sb); LIST_HEAD(list); @@ -1159,7 +1167,9 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir, goto out; } - old_cred = ovl_override_creds(old->d_sb); + err = ovl_override_creds(old->d_sb, &old_cred); + if (err) + goto out_revert_creds; if (!list_empty(&list)) { opaquedir = ovl_clear_empty(new, &list); @@ -1292,7 +1302,7 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir, out_unlock: unlock_rename(new_upperdir, old_upperdir); out_revert_creds: - revert_creds(old_cred); + ovl_revert_creds(&old_cred); if (update_nlink) ovl_nlink_end(new); else @@ -1306,7 +1316,7 @@ static int ovl_rename(struct mnt_idmap *idmap, struct inode *olddir, static int ovl_create_tmpfile(struct file *file, struct dentry *dentry, struct inode *inode, umode_t mode) { - const struct cred *old_cred; + struct ovl_creds_desc old_cred; struct path realparentpath; struct file *realfile; struct dentry *newdentry; @@ -1314,8 +1324,11 @@ static int ovl_create_tmpfile(struct file *file, struct dentry *dentry, int flags = file->f_flags | OVL_OPEN_FLAGS; int err; - old_cred = ovl_override_creds(dentry->d_sb); - err = ovl_setup_cred_for_create(dentry, inode, mode, old_cred); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + return err; + + err = ovl_setup_cred_for_create(dentry, inode, mode, &old_cred); if (err) goto out_revert_creds; @@ -1337,7 +1350,7 @@ static int ovl_create_tmpfile(struct file *file, struct dentry *dentry, fput(realfile); } out_revert_creds: - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return err; } diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 84aad9d19bdd..3762998be706 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -31,7 +31,7 @@ static struct file *ovl_open_realfile(const struct file *file, struct inode *inode = file_inode(file); struct mnt_idmap *real_idmap; struct file *realfile; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int flags = file->f_flags | OVL_OPEN_FLAGS; int acc_mode = ACC_MODE(flags); int err; @@ -39,7 +39,10 @@ static struct file *ovl_open_realfile(const struct file *file, if (flags & O_APPEND) acc_mode |= MAY_APPEND; - old_cred = ovl_override_creds(inode->i_sb); + err = ovl_override_creds(inode->i_sb, &old_cred); + if (err) + return ERR_PTR(err); + real_idmap = mnt_idmap(realpath->mnt); err = inode_permission(real_idmap, realinode, MAY_OPEN | acc_mode); if (err) { @@ -51,7 +54,7 @@ static struct file *ovl_open_realfile(const struct file *file, realfile = backing_file_open(file, flags, realpath, current_cred()); } - revert_creds(old_cred); + ovl_revert_creds(&old_cred); pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n", file, file, ovl_whatisit(inode, realinode), file->f_flags, @@ -184,7 +187,7 @@ static loff_t ovl_llseek(struct file *file, loff_t offset, int whence) { struct inode *inode = file_inode(file); struct fd real; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; loff_t ret; /* @@ -213,9 +216,10 @@ static loff_t ovl_llseek(struct file *file, loff_t offset, int whence) ovl_inode_lock(inode); fd_file(real)->f_pos = file->f_pos; - old_cred = ovl_override_creds(inode->i_sb); - ret = vfs_llseek(fd_file(real), offset, whence); - revert_creds(old_cred); + ret = ovl_override_creds(inode->i_sb, &old_cred); + if (!ret) + ret = vfs_llseek(fd_file(real), offset, whence); + ovl_revert_creds(&old_cred); file->f_pos = fd_file(real)->f_pos; ovl_inode_unlock(inode); @@ -392,7 +396,7 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out, static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync) { struct fd real; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int ret; ret = ovl_sync_status(OVL_FS(file_inode(file)->i_sb)); @@ -405,9 +409,10 @@ static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync) /* Don't sync lower file for fear of receiving EROFS error */ if (file_inode(fd_file(real)) == ovl_inode_upper(file_inode(file))) { - old_cred = ovl_override_creds(file_inode(file)->i_sb); - ret = vfs_fsync_range(fd_file(real), start, end, datasync); - revert_creds(old_cred); + ret = ovl_override_creds(file_inode(file)->i_sb, &old_cred); + if (!ret) + ret = vfs_fsync_range(fd_file(real), start, end, datasync); + ovl_revert_creds(&old_cred); } fdput(real); @@ -431,7 +436,7 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len { struct inode *inode = file_inode(file); struct fd real; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int ret; inode_lock(inode); @@ -445,9 +450,10 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len if (ret) goto out_unlock; - old_cred = ovl_override_creds(file_inode(file)->i_sb); - ret = vfs_fallocate(fd_file(real), mode, offset, len); - revert_creds(old_cred); + ret = ovl_override_creds(file_inode(file)->i_sb, &old_cred); + if (!ret) + ret = vfs_fallocate(fd_file(real), mode, offset, len); + ovl_revert_creds(&old_cred); /* Update size */ ovl_file_modified(file); @@ -463,16 +469,17 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len static int ovl_fadvise(struct file *file, loff_t offset, loff_t len, int advice) { struct fd real; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int ret; ret = ovl_real_fdget(file, &real); if (ret) return ret; - old_cred = ovl_override_creds(file_inode(file)->i_sb); - ret = vfs_fadvise(fd_file(real), offset, len, advice); - revert_creds(old_cred); + ret = ovl_override_creds(file_inode(file)->i_sb, &old_cred); + if (!ret) + ret = vfs_fadvise(fd_file(real), offset, len, advice); + ovl_revert_creds(&old_cred); fdput(real); @@ -491,7 +498,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, { struct inode *inode_out = file_inode(file_out); struct fd real_in, real_out; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; loff_t ret; inode_lock(inode_out); @@ -513,7 +520,10 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, goto out_unlock; } - old_cred = ovl_override_creds(file_inode(file_out)->i_sb); + ret = ovl_override_creds(file_inode(file_out)->i_sb, &old_cred); + if (ret) + goto skip_switch; + switch (op) { case OVL_COPY: ret = vfs_copy_file_range(fd_file(real_in), pos_in, @@ -531,7 +541,9 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, flags); break; } - revert_creds(old_cred); + +skip_switch: + ovl_revert_creds(&old_cred); /* Update size */ ovl_file_modified(file_out); @@ -583,7 +595,7 @@ static loff_t ovl_remap_file_range(struct file *file_in, loff_t pos_in, static int ovl_flush(struct file *file, fl_owner_t id) { struct fd real; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int err; err = ovl_real_fdget(file, &real); @@ -591,9 +603,10 @@ static int ovl_flush(struct file *file, fl_owner_t id) return err; if (fd_file(real)->f_op->flush) { - old_cred = ovl_override_creds(file_inode(file)->i_sb); - err = fd_file(real)->f_op->flush(fd_file(real), id); - revert_creds(old_cred); + err = ovl_override_creds(file_inode(file)->i_sb, &old_cred); + if (!err) + err = fd_file(real)->f_op->flush(fd_file(real), id); + ovl_revert_creds(&old_cred); } fdput(real); diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 8b31f44c12cd..2d27bafad986 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -25,7 +25,7 @@ int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct ovl_fs *ofs = OVL_FS(dentry->d_sb); bool full_copy_up = false; struct dentry *upperdentry; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; err = setattr_prepare(&nop_mnt_idmap, dentry, attr); if (err) @@ -78,9 +78,10 @@ int ovl_setattr(struct mnt_idmap *idmap, struct dentry *dentry, goto out_put_write; inode_lock(upperdentry->d_inode); - old_cred = ovl_override_creds(dentry->d_sb); - err = ovl_do_notify_change(ofs, upperdentry, attr); - revert_creds(old_cred); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (!err) + err = ovl_do_notify_change(ofs, upperdentry, attr); + ovl_revert_creds(&old_cred); if (!err) ovl_copyattr(dentry->d_inode); inode_unlock(upperdentry->d_inode); @@ -159,7 +160,7 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path, struct dentry *dentry = path->dentry; enum ovl_path_type type; struct path realpath; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; struct inode *inode = d_inode(dentry); bool is_dir = S_ISDIR(inode->i_mode); int fsid = 0; @@ -169,8 +170,10 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path, metacopy_blocks = ovl_is_metacopy_dentry(dentry); type = ovl_path_real(dentry, &realpath); - old_cred = ovl_override_creds(dentry->d_sb); - err = vfs_getattr_nosec(&realpath, stat, request_mask, flags); + + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (!err) + err = vfs_getattr_nosec(&realpath, stat, request_mask, flags); if (err) goto out; @@ -280,7 +283,7 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path, stat->nlink = dentry->d_inode->i_nlink; out: - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return err; } @@ -291,7 +294,7 @@ int ovl_permission(struct mnt_idmap *idmap, struct inode *upperinode = ovl_inode_upper(inode); struct inode *realinode; struct path realpath; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int err; /* Careful in RCU walk mode */ @@ -309,7 +312,10 @@ int ovl_permission(struct mnt_idmap *idmap, if (err) return err; - old_cred = ovl_override_creds(inode->i_sb); + err = ovl_override_creds(inode->i_sb, &old_cred); + if (err) + return err; + if (!upperinode && !special_file(realinode->i_mode) && mask & MAY_WRITE) { mask &= ~(MAY_WRITE | MAY_APPEND); @@ -317,7 +323,7 @@ int ovl_permission(struct mnt_idmap *idmap, mask |= MAY_READ; } err = inode_permission(mnt_idmap(realpath.mnt), realinode, mask); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return err; } @@ -326,15 +332,19 @@ static const char *ovl_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) { - const struct cred *old_cred; + struct ovl_creds_desc old_cred; const char *p; + int err; if (!dentry) return ERR_PTR(-ECHILD); - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + return ERR_PTR(err); + p = vfs_get_link(ovl_dentry_real(dentry), done); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return p; } @@ -465,11 +475,15 @@ struct posix_acl *do_ovl_get_acl(struct mnt_idmap *idmap, acl = get_cached_acl_rcu(realinode, type); } else { - const struct cred *old_cred; + struct ovl_creds_desc old_cred; + int err; + + err = ovl_override_creds(inode->i_sb, &old_cred); + if (err) + return ERR_PTR(err); - old_cred = ovl_override_creds(inode->i_sb); acl = ovl_get_acl_path(&realpath, posix_acl_xattr_name(type), noperm); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); } return acl; @@ -481,7 +495,7 @@ static int ovl_set_or_remove_acl(struct dentry *dentry, struct inode *inode, int err; struct path realpath; const char *acl_name; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; struct ovl_fs *ofs = OVL_FS(dentry->d_sb); struct dentry *upperdentry = ovl_dentry_upper(dentry); struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry); @@ -495,10 +509,14 @@ static int ovl_set_or_remove_acl(struct dentry *dentry, struct inode *inode, struct posix_acl *real_acl; ovl_path_lower(dentry, &realpath); - old_cred = ovl_override_creds(dentry->d_sb); + + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + return err; + real_acl = vfs_get_acl(mnt_idmap(realpath.mnt), realdentry, acl_name); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); if (IS_ERR(real_acl)) { err = PTR_ERR(real_acl); goto out; @@ -518,12 +536,17 @@ static int ovl_set_or_remove_acl(struct dentry *dentry, struct inode *inode, if (err) goto out; - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + goto out_revert; + if (acl) err = ovl_do_set_acl(ofs, realdentry, acl_name, acl); else err = ovl_do_remove_acl(ofs, realdentry, acl_name); - revert_creds(old_cred); + +out_revert: + ovl_revert_creds(&old_cred); ovl_drop_write(dentry); /* copy c/mtime */ @@ -590,7 +613,7 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, { int err; struct inode *realinode = ovl_inode_realdata(inode); - const struct cred *old_cred; + struct ovl_creds_desc old_cred; if (!realinode) return -EIO; @@ -598,9 +621,10 @@ static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, if (!realinode->i_op->fiemap) return -EOPNOTSUPP; - old_cred = ovl_override_creds(inode->i_sb); - err = realinode->i_op->fiemap(realinode, fieinfo, start, len); - revert_creds(old_cred); + err = ovl_override_creds(inode->i_sb, &old_cred); + if (!err) + err = realinode->i_op->fiemap(realinode, fieinfo, start, len); + ovl_revert_creds(&old_cred); return err; } @@ -648,7 +672,7 @@ int ovl_fileattr_set(struct mnt_idmap *idmap, { struct inode *inode = d_inode(dentry); struct path upperpath; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; unsigned int flags; int err; @@ -660,7 +684,7 @@ int ovl_fileattr_set(struct mnt_idmap *idmap, if (err) goto out; - old_cred = ovl_override_creds(inode->i_sb); + err = ovl_override_creds(inode->i_sb, &old_cred); /* * Store immutable/append-only flags in xattr and clear them * in upper fileattr (in case they were set by older kernel) @@ -668,10 +692,11 @@ int ovl_fileattr_set(struct mnt_idmap *idmap, * "ovl-immutable" hardlinks could be copied up. * Clear xattr when flags are cleared. */ - err = ovl_set_protattr(inode, upperpath.dentry, fa); + if (!err) + err = ovl_set_protattr(inode, upperpath.dentry, fa); if (!err) err = ovl_real_fileattr_set(&upperpath, fa); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); ovl_drop_write(dentry); /* @@ -725,15 +750,18 @@ int ovl_fileattr_get(struct dentry *dentry, struct fileattr *fa) { struct inode *inode = d_inode(dentry); struct path realpath; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int err; ovl_path_real(dentry, &realpath); - old_cred = ovl_override_creds(inode->i_sb); + err = ovl_override_creds(inode->i_sb, &old_cred); + if (err) + return err; + err = ovl_real_fileattr_get(&realpath, fa); ovl_fileattr_prot_flags(inode, fa); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return err; } diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index efa2a072aa69..edc11a7b27ee 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -969,15 +969,19 @@ static int ovl_maybe_validate_verity(struct dentry *dentry) return err; if (!ovl_test_flag(OVL_VERIFIED_DIGEST, inode)) { - const struct cred *old_cred; + struct ovl_creds_desc old_cred; - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) { + ovl_inode_unlock(inode); + return err; + } err = ovl_validate_verity(ofs, &metapath, &datapath); if (err == 0) ovl_set_flag(OVL_VERIFIED_DIGEST, inode); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); } ovl_inode_unlock(inode); @@ -991,7 +995,7 @@ static int ovl_maybe_lookup_lowerdata(struct dentry *dentry) struct inode *inode = d_inode(dentry); const char *redirect = ovl_lowerdata_redirect(inode); struct ovl_path datapath = {}; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int err; if (!redirect || ovl_dentry_lowerdata(dentry)) @@ -1009,9 +1013,12 @@ static int ovl_maybe_lookup_lowerdata(struct dentry *dentry) if (ovl_dentry_lowerdata(dentry)) goto out; - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + goto out_err; + err = ovl_lookup_data_layers(dentry, redirect, &datapath); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); if (err) goto out_err; @@ -1071,7 +1078,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { struct ovl_entry *oe = NULL; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; struct ovl_fs *ofs = OVL_FS(dentry->d_sb); struct ovl_entry *poe = OVL_E(dentry->d_parent); struct ovl_entry *roe = OVL_E(dentry->d_sb->s_root); @@ -1104,7 +1111,10 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, if (dentry->d_name.len > ofs->namelen) return ERR_PTR(-ENAMETOOLONG); - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + return ERR_PTR(err); + upperdir = ovl_dentry_upper(dentry->d_parent); if (upperdir) { d.layer = &ofs->layers[0]; @@ -1378,7 +1388,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, ovl_dentry_init_reval(dentry, upperdentry, OVL_I_E(inode)); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); if (origin_path) { dput(origin_path->dentry); kfree(origin_path); @@ -1402,7 +1412,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, kfree(d.upperredirect); out: kfree(d.redirect); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return ERR_PTR(err); } @@ -1410,7 +1420,7 @@ bool ovl_lower_positive(struct dentry *dentry) { struct ovl_entry *poe = OVL_E(dentry->d_parent); const struct qstr *name = &dentry->d_name; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; unsigned int i; bool positive = false; bool done = false; @@ -1426,7 +1436,10 @@ bool ovl_lower_positive(struct dentry *dentry) if (!ovl_dentry_upper(dentry)) return true; - old_cred = ovl_override_creds(dentry->d_sb); + /* Ugh, hard - we can't pass an error from here. */ + if (ovl_override_creds(dentry->d_sb, &old_cred)) + return false; + /* Positive upper -> have to look up lower to see whether it exists */ for (i = 0; !done && !positive && i < ovl_numlower(poe); i++) { struct dentry *this; @@ -1459,7 +1472,7 @@ bool ovl_lower_positive(struct dentry *dentry) dput(this); } } - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return positive; } diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 8577c7884fb9..4297912b0cc4 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -164,6 +164,12 @@ struct ovl_metacopy { u8 digest[FS_VERITY_MAX_DIGEST_SIZE]; /* Only the used part on disk */ } __packed; +/* Credential information used by overlay */ +struct ovl_creds_desc { + const struct cred *cred; + struct ve_struct *ve; +}; + #define OVL_METACOPY_MAX_SIZE (sizeof(struct ovl_metacopy)) #define OVL_METACOPY_MIN_SIZE (OVL_METACOPY_MAX_SIZE - FS_VERITY_MAX_DIGEST_SIZE) #define OVL_METACOPY_INIT { 0, OVL_METACOPY_MIN_SIZE } @@ -420,7 +426,8 @@ void ovl_end_write(struct dentry *dentry); int ovl_want_write(struct dentry *dentry); void ovl_drop_write(struct dentry *dentry); struct dentry *ovl_workdir(struct dentry *dentry); -const struct cred *ovl_override_creds(struct super_block *sb); +int ovl_override_creds(struct super_block *sb, struct ovl_creds_desc *desc); +void ovl_revert_creds(struct ovl_creds_desc *old_creds); static inline const struct cred *ovl_creds(struct super_block *sb) { diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index 0ca8af060b0c..478b0a32ff64 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -273,9 +273,11 @@ static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data int err; struct ovl_cache_entry *p; struct dentry *dentry, *dir = path->dentry; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; - old_cred = ovl_override_creds(rdd->dentry->d_sb); + err = ovl_override_creds(rdd->dentry->d_sb, &old_cred); + if (err) + return err; err = down_write_killable(&dir->d_inode->i_rwsem); if (!err) { @@ -290,7 +292,7 @@ static int ovl_check_whiteouts(const struct path *path, struct ovl_readdir_data } inode_unlock(dir->d_inode); } - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return err; } @@ -753,10 +755,13 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) struct dentry *dentry = file->f_path.dentry; struct ovl_fs *ofs = OVL_FS(dentry->d_sb); struct ovl_cache_entry *p; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int err; - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + return err; + if (!ctx->pos) ovl_dir_reset(file); @@ -808,7 +813,7 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) } err = 0; out: - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return err; } @@ -856,11 +861,15 @@ static struct file *ovl_dir_open_realfile(const struct file *file, const struct path *realpath) { struct file *res; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; + int err; + + err = ovl_override_creds(file_inode(file)->i_sb, &old_cred); + if (err) + return ERR_PTR(err); - old_cred = ovl_override_creds(file_inode(file)->i_sb); res = ovl_path_open(realpath, O_RDONLY | (file->f_flags & O_LARGEFILE)); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); return res; } @@ -983,11 +992,14 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list) int err; struct ovl_cache_entry *p, *n; struct rb_root root = RB_ROOT; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; + + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + return err; - old_cred = ovl_override_creds(dentry->d_sb); err = ovl_dir_read_merged(dentry, list, &root); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); if (err) return err; diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index f95090f0d29c..d28d572d6099 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -63,11 +63,27 @@ struct dentry *ovl_workdir(struct dentry *dentry) return ofs->workdir; } -const struct cred *ovl_override_creds(struct super_block *sb) +/* On error no revert is needed. */ +int ovl_override_creds(struct super_block *sb, struct ovl_creds_desc *desc) { struct ovl_fs *ofs = OVL_FS(sb); - return override_creds(ofs->creator_cred); + desc->ve = override_ve(ofs->creator_ve); + if (IS_ERR(desc->ve)) + return PTR_ERR(desc->ve); + + desc->cred = override_creds(ofs->creator_cred); + return 0; +} + +/* Accepts desc from a failed ovl_override_creds and does nothing. */ +void ovl_revert_creds(struct ovl_creds_desc *old_creds) +{ + if (IS_ERR(old_creds->ve)) + return; + + revert_creds(old_creds->cred); + revert_ve(old_creds->ve); } /* @@ -1150,7 +1166,7 @@ static void ovl_cleanup_index(struct dentry *dentry) int ovl_nlink_start(struct dentry *dentry) { struct inode *inode = d_inode(dentry); - const struct cred *old_cred; + struct ovl_creds_desc old_cred; int err; if (WARN_ON(!inode)) @@ -1187,7 +1203,10 @@ int ovl_nlink_start(struct dentry *dentry) if (d_is_dir(dentry) || !ovl_test_flag(OVL_INDEX, inode)) return 0; - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + goto out_drop_write; + /* * The overlay inode nlink should be incremented/decremented IFF the * upper operation succeeds, along with nlink change of upper inode. @@ -1195,7 +1214,7 @@ int ovl_nlink_start(struct dentry *dentry) * value relative to the upper inode nlink in an upper inode xattr. */ err = ovl_set_nlink_upper(dentry); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); if (err) goto out_drop_write; @@ -1216,11 +1235,15 @@ void ovl_nlink_end(struct dentry *dentry) ovl_drop_write(dentry); if (ovl_test_flag(OVL_INDEX, inode) && inode->i_nlink == 0) { - const struct cred *old_cred; + struct ovl_creds_desc old_cred; + int err; - old_cred = ovl_override_creds(dentry->d_sb); - ovl_cleanup_index(dentry); - revert_creds(old_cred); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + pr_err("%s: skipping ovl_cleanup_index.\n", __func__); + else + ovl_cleanup_index(dentry); + ovl_revert_creds(&old_cred); } ovl_inode_unlock(inode); diff --git a/fs/overlayfs/xattrs.c b/fs/overlayfs/xattrs.c index 0ed2b049056d..7528ec76868d 100644 --- a/fs/overlayfs/xattrs.c +++ b/fs/overlayfs/xattrs.c @@ -41,13 +41,16 @@ static int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char struct dentry *upperdentry = ovl_i_dentry_upper(inode); struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry); struct path realpath; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; if (!value && !upperdentry) { ovl_path_lower(dentry, &realpath); - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) + return err; + err = vfs_getxattr(mnt_idmap(realpath.mnt), realdentry, name, NULL, 0); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); if (err < 0) goto out; } @@ -64,7 +67,12 @@ static int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char if (err) goto out; - old_cred = ovl_override_creds(dentry->d_sb); + err = ovl_override_creds(dentry->d_sb, &old_cred); + if (err) { + ovl_drop_write(dentry); + return err; + } + if (value) { err = ovl_do_setxattr(ofs, realdentry, name, value, size, flags); @@ -72,7 +80,7 @@ static int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char WARN_ON(flags != XATTR_REPLACE); err = ovl_do_removexattr(ofs, realdentry, name); } - revert_creds(old_cred); + ovl_revert_creds(&old_cred); ovl_drop_write(dentry); /* copy c/mtime */ @@ -85,13 +93,14 @@ static int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char void *value, size_t size) { ssize_t res; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; struct path realpath; ovl_i_path_real(inode, &realpath); - old_cred = ovl_override_creds(dentry->d_sb); - res = vfs_getxattr(mnt_idmap(realpath.mnt), realpath.dentry, name, value, size); - revert_creds(old_cred); + res = ovl_override_creds(dentry->d_sb, &old_cred); + if (!res) + res = vfs_getxattr(mnt_idmap(realpath.mnt), realpath.dentry, name, value, size); + ovl_revert_creds(&old_cred); return res; } @@ -116,12 +125,14 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) ssize_t res; size_t len; char *s; - const struct cred *old_cred; + struct ovl_creds_desc old_cred; size_t prefix_len, name_len; - old_cred = ovl_override_creds(dentry->d_sb); + res = ovl_override_creds(dentry->d_sb, &old_cred); + if (res) + return res; res = vfs_listxattr(realdentry, list, size); - revert_creds(old_cred); + ovl_revert_creds(&old_cred); if (res <= 0 || size == 0) return res; -- 2.52.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel