Re: [bug report] fanotify: support reporting non-decodeable file handles

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 24, 2023 at 9:34 AM Dan Carpenter <dan.carpenter@xxxxxxxxxx> wrote:
>
> Hello Amir Goldstein,
>
> The patch 7ba39960c7f3: "fanotify: support reporting non-decodeable
> file handles" from May 2, 2023, leads to the following Smatch static
> checker warning:
>
>         fs/notify/fanotify/fanotify.c:451 fanotify_encode_fh()
>         warn: assigning signed to unsigned: 'fh->type = type' 's32min-(-1),1-254,256-s32max'
>
> (unpublished garbage Smatch check).
>
> fs/notify/fanotify/fanotify.c
>     403 static int fanotify_encode_fh(struct fanotify_fh *fh, struct inode *inode,
>     404                               unsigned int fh_len, unsigned int *hash,
>     405                               gfp_t gfp)
>     406 {
>     407         int dwords, type = 0;
>     408         char *ext_buf = NULL;
>     409         void *buf = fh->buf;
>     410         int err;
>     411
>     412         fh->type = FILEID_ROOT;
>     413         fh->len = 0;
>     414         fh->flags = 0;
>     415
>     416         /*
>     417          * Invalid FHs are used by FAN_FS_ERROR for errors not
>     418          * linked to any inode. The f_handle won't be reported
>     419          * back to userspace.
>     420          */
>     421         if (!inode)
>     422                 goto out;
>     423
>     424         /*
>     425          * !gpf means preallocated variable size fh, but fh_len could
>     426          * be zero in that case if encoding fh len failed.
>     427          */
>     428         err = -ENOENT;
>     429         if (fh_len < 4 || WARN_ON_ONCE(fh_len % 4) || fh_len > MAX_HANDLE_SZ)
>     430                 goto out_err;
>     431
>     432         /* No external buffer in a variable size allocated fh */
>     433         if (gfp && fh_len > FANOTIFY_INLINE_FH_LEN) {
>     434                 /* Treat failure to allocate fh as failure to encode fh */
>     435                 err = -ENOMEM;
>     436                 ext_buf = kmalloc(fh_len, gfp);
>     437                 if (!ext_buf)
>     438                         goto out_err;
>     439
>     440                 *fanotify_fh_ext_buf_ptr(fh) = ext_buf;
>     441                 buf = ext_buf;
>     442                 fh->flags |= FANOTIFY_FH_FLAG_EXT_BUF;
>     443         }
>     444
>     445         dwords = fh_len >> 2;
>     446         type = exportfs_encode_fid(inode, buf, &dwords);
>     447         err = -EINVAL;
>     448         if (!type || type == FILEID_INVALID || fh_len != dwords << 2)
>
> exportfs_encode_fid() can return negative errors.  Do we need to check
> if (!type etc?

Well, it is true that exportfs_encode_fid() can return a negative value
in principle, as did exportfs_encode_fh() before it, if there was a filesystem
implementation of ->encode_fh() that returned a negative value.
AFAIK, there currently is no such implementation in-tree, otherwise current
upstream code would have been buggy.

Patch 2/4 adds a new possible -EOPNOTSUPP return value from
exportfs_encode_inode_fh() and even goes further to add a kerndoc:
 * Returns an enum fid_type or a negative errno.
But this new return value is not possible from exportfs_encode_fid()
that is used here and in {fa,i}notify_fdinfo().

All the rest of the callers (nfsd, overlayfs, name_to_hanle_at) already
check this same EOPNOTSUPP condition before calling, but there is
no guarantee that this will not change in the future.

All the callers mentioned above check the unexpected return value differently:
nfsd: only type == FILEID_INVALID
fdinfo: type < 0 || type == FILEID_INVALID
fanotify: !type || type == FILEID_INVALID
overlayfs: type < 0 || type == FILEID_INVALID
name_to_hanle_at: (retval == FILEID_INVALID) || (retval == -ENOSPC))
                /* As per old exportfs_encode_fh documentation
                 * we could return ENOSPC to indicate overflow
                 * But file system returned 255 always. So handle
                 * both the values
                 */

So he have a bit of a mess.
How should we clean it up?

Option #1: Change encode_fh to return unsigned and replace that new
                  EOPNOTSUPP with FILEID_INVALID
Option #2: change all callers to check negative return value

I am in favor of option #2.
Shall I send a patch?

Thanks,
Amir.




[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux