ovl: return required buffer size for file handles

Overlayfs doesn't work well with the fanotify mechanism.

Fanotify first probes for the required buffer size for the file handle,
but overlayfs currently bails out without passing the size back.

That results in errors in the kernel log, such as:

[527944.485384] overlayfs: failed to encode file handle (/, err=-75, buflen=0, len=29, type=1)
[527944.485386] fanotify: failed to encode fid (fsid=ae521e68.a434d95f, type=255, bytes=0, err=-2)

Signed-off-by: Lubos Dolezel <lubos@dolezel.info>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
Lubos Dolezel 2020-05-04 21:35:09 +02:00 коммит произвёл Miklos Szeredi
Родитель 399c109d35
Коммит 144da23bea
1 изменённых файлов: 8 добавлений и 10 удалений

Просмотреть файл

@ -231,11 +231,8 @@ static int ovl_dentry_to_fid(struct dentry *dentry, u32 *fid, int buflen)
if (IS_ERR(fh)) if (IS_ERR(fh))
return PTR_ERR(fh); return PTR_ERR(fh);
err = -EOVERFLOW;
len = OVL_FH_LEN(fh); len = OVL_FH_LEN(fh);
if (len > buflen) if (len <= buflen)
goto fail;
memcpy(fid, fh, len); memcpy(fid, fh, len);
err = len; err = len;
@ -244,9 +241,8 @@ out:
return err; return err;
fail: fail:
pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i, buflen=%d, len=%d, type=%d)\n", pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i)\n",
dentry, err, buflen, fh ? (int)fh->fb.len : 0, dentry, err);
fh ? fh->fb.type : 0);
goto out; goto out;
} }
@ -254,7 +250,7 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len,
struct inode *parent) struct inode *parent)
{ {
struct dentry *dentry; struct dentry *dentry;
int bytes = *max_len << 2; int bytes, buflen = *max_len << 2;
/* TODO: encode connectable file handles */ /* TODO: encode connectable file handles */
if (parent) if (parent)
@ -264,12 +260,14 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len,
if (WARN_ON(!dentry)) if (WARN_ON(!dentry))
return FILEID_INVALID; return FILEID_INVALID;
bytes = ovl_dentry_to_fid(dentry, fid, bytes); bytes = ovl_dentry_to_fid(dentry, fid, buflen);
dput(dentry); dput(dentry);
if (bytes <= 0) if (bytes <= 0)
return FILEID_INVALID; return FILEID_INVALID;
*max_len = bytes >> 2; *max_len = bytes >> 2;
if (bytes > buflen)
return FILEID_INVALID;
return OVL_FILEID_V1; return OVL_FILEID_V1;
} }