From d5b3108d95f0c2b4cfedd33658661112f015bebb Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Fri, 13 Sep 2019 08:25:31 -0700 Subject: [PATCH] ANDROID: regression introduced override_creds=off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Solve a regression introduced by commit 272fcd1ca7ceb252b1c3a2961110c7c1722707cf ("ANDROID: overlayfs: override_creds=off option bypass creator_cred") where a crash is observed a crash in ovl_create_or_link() when a simple re-direction command in vendor directory. /vendor/bin/ > /vendor/bin/test_log.txt 2>&1& After further debugging we see that if the output is redirected to a file which doesn’t exist we see this stack: [ 377.382745] ovl_create_or_link+0xac/0x710 [ 377.382745] ovl_create_object+0xb8/0x110 [ 377.382745] ovl_create+0x34/0x40 [ 377.382745] path_openat+0xd44/0x15a8 [ 377.382745] do_filp_open+0x80/0x128 [ 377.382745] do_sys_open+0x140/0x250 [ 377.382745] __arm64_sys_openat+0x2c/0x38 ovl_override_creds returns NULL because the override_cred flag is set to false. This causes ovl_revert_creds also to fail. There is another call to check override_cred in override_cred call which overrides the creds permanently as there no revert_creds associated. So whenever next commit_cred is called we see the crash as the credentials are permanently overridden. Signed-off-by: Mark Salyzyn Tested-by: Rishabh/Jeevan Bug: 140816499 Change-Id: Icd0d9be82fc57af5ead1eeab99f79adf3adf62ef --- fs/overlayfs/dir.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index d0a892030a5e..57cf4b64326a 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -540,7 +540,7 @@ 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; + const struct cred *old_cred, *hold_cred = NULL; struct cred *override_cred; struct dentry *parent = dentry->d_parent; @@ -575,7 +575,7 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, goto out_revert_creds; } } - put_cred(override_creds(override_cred)); + hold_cred = override_creds(override_cred); put_cred(override_cred); if (!ovl_dentry_is_whiteout(dentry)) @@ -584,7 +584,9 @@ static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, err = ovl_create_over_whiteout(dentry, inode, attr); } out_revert_creds: - ovl_revert_creds(old_cred); + ovl_revert_creds(old_cred ?: hold_cred); + if (old_cred && hold_cred) + put_cred(hold_cred); return err; }