Skip to content

Commit 530f32f

Browse files
author
Miklos Szeredi
committed
aio: fix async fsync creds
Avi Kivity reports that on fuse filesystems running in a user namespace asyncronous fsync fails with EOVERFLOW. The reason is that f_ops->fsync() is called with the creds of the kthread performing aio work instead of the creds of the process originally submitting IOCB_CMD_FSYNC. Fuse sends the creds of the caller in the request header and it needs to translate the uid and gid into the server's user namespace. Since the kthread is running in init_user_ns, the translation will fail and the operation returns an error. It can be argued that fsync doesn't actually need any creds, but just zeroing out those fields in the header (as with requests that currently don't take creds) is a backward compatibility risk. Instead of working around this issue in fuse, solve the core of the problem by calling the filesystem with the proper creds. Reported-by: Avi Kivity <[email protected]> Tested-by: Giuseppe Scrivano <[email protected]> Fixes: c9582eb ("fuse: Fail all requests with invalid uids or gids") Cc: [email protected] # 4.18+ Signed-off-by: Miklos Szeredi <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>
1 parent a3c751a commit 530f32f

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

fs/aio.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ struct fsync_iocb {
176176
struct file *file;
177177
struct work_struct work;
178178
bool datasync;
179+
struct cred *creds;
179180
};
180181

181182
struct poll_iocb {
@@ -1589,8 +1590,11 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb,
15891590
static void aio_fsync_work(struct work_struct *work)
15901591
{
15911592
struct aio_kiocb *iocb = container_of(work, struct aio_kiocb, fsync.work);
1593+
const struct cred *old_cred = override_creds(iocb->fsync.creds);
15921594

15931595
iocb->ki_res.res = vfs_fsync(iocb->fsync.file, iocb->fsync.datasync);
1596+
revert_creds(old_cred);
1597+
put_cred(iocb->fsync.creds);
15941598
iocb_put(iocb);
15951599
}
15961600

@@ -1604,6 +1608,10 @@ static int aio_fsync(struct fsync_iocb *req, const struct iocb *iocb,
16041608
if (unlikely(!req->file->f_op->fsync))
16051609
return -EINVAL;
16061610

1611+
req->creds = prepare_creds();
1612+
if (!req->creds)
1613+
return -ENOMEM;
1614+
16071615
req->datasync = datasync;
16081616
INIT_WORK(&req->work, aio_fsync_work);
16091617
schedule_work(&req->work);

0 commit comments

Comments
 (0)