]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs: Replace user_access_{begin/end} by scoped user access
authorChristophe Leroy (CS GROUP) <chleroy@kernel.org>
Tue, 24 Mar 2026 11:41:16 +0000 (12:41 +0100)
committerChristian Brauner <brauner@kernel.org>
Tue, 24 Mar 2026 13:44:02 +0000 (14:44 +0100)
Scoped user access reduces code complexity and seamlessly bring
masked user access on architectures that support it.

Replace user_access_begin/user_access_end blocks by
scoped user access.

Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Link: https://patch.msgid.link/16daf33a8190a771a93e294d050bd8153521ffca.1774350128.git.chleroy@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/readdir.c
fs/select.c

index fb910dc2f52b597b8cbc53c3f43eeb443cf895f8..76bb1ae3a450418182d8cd30a4baaa81efc9d88c 100644 (file)
@@ -200,16 +200,13 @@ static bool fillonedir(struct dir_context *ctx, const char *name, int namlen,
        }
        buf->result++;
        dirent = buf->dirent;
-       if (!user_write_access_begin(dirent, dirent_size(dirent, namlen + 1)))
-               goto efault;
-       unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
-       unsafe_put_user(offset, &dirent->d_offset, efault_end);
-       unsafe_put_user(namlen, &dirent->d_namlen, efault_end);
-       unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
-       user_write_access_end();
+       scoped_user_write_access_size(dirent, dirent_size(dirent, namlen + 1), efault) {
+               unsafe_put_user(d_ino, &dirent->d_ino, efault);
+               unsafe_put_user(offset, &dirent->d_offset, efault);
+               unsafe_put_user(namlen, &dirent->d_namlen, efault);
+               unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+       }
        return true;
-efault_end:
-       user_write_access_end();
 efault:
        buf->result = -EFAULT;
        return false;
@@ -286,23 +283,19 @@ static bool filldir(struct dir_context *ctx, const char *name, int namlen,
                return false;
        dirent = buf->current_dir;
        prev = (void __user *) dirent - prev_reclen;
-       if (!user_write_access_begin(prev, reclen + prev_reclen))
-               goto efault;
-
-       /* This might be 'dirent->d_off', but if so it will get overwritten */
-       unsafe_put_user(offset, &prev->d_off, efault_end);
-       unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
-       unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
-       unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
-       unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
-       user_write_access_end();
+       scoped_user_write_access_size(prev, reclen + prev_reclen, efault) {
+               /* This might be 'dirent->d_off', but if so it will get overwritten */
+               unsafe_put_user(offset, &prev->d_off, efault);
+               unsafe_put_user(d_ino, &dirent->d_ino, efault);
+               unsafe_put_user(reclen, &dirent->d_reclen, efault);
+               unsafe_put_user(d_type, (char __user *)dirent + reclen - 1, efault);
+               unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+       }
 
        buf->current_dir = (void __user *)dirent + reclen;
        buf->prev_reclen = reclen;
        ctx->count -= reclen;
        return true;
-efault_end:
-       user_write_access_end();
 efault:
        buf->error = -EFAULT;
        return false;
@@ -369,24 +362,20 @@ static bool filldir64(struct dir_context *ctx, const char *name, int namlen,
                return false;
        dirent = buf->current_dir;
        prev = (void __user *)dirent - prev_reclen;
-       if (!user_write_access_begin(prev, reclen + prev_reclen))
-               goto efault;
-
-       /* This might be 'dirent->d_off', but if so it will get overwritten */
-       unsafe_put_user(offset, &prev->d_off, efault_end);
-       unsafe_put_user(ino, &dirent->d_ino, efault_end);
-       unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
-       unsafe_put_user(d_type, &dirent->d_type, efault_end);
-       unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
-       user_write_access_end();
+       scoped_user_write_access_size(prev, reclen + prev_reclen, efault) {
+               /* This might be 'dirent->d_off', but if so it will get overwritten */
+               unsafe_put_user(offset, &prev->d_off, efault);
+               unsafe_put_user(ino, &dirent->d_ino, efault);
+               unsafe_put_user(reclen, &dirent->d_reclen, efault);
+               unsafe_put_user(d_type, &dirent->d_type, efault);
+               unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+       }
 
        buf->prev_reclen = reclen;
        buf->current_dir = (void __user *)dirent + reclen;
        ctx->count -= reclen;
        return true;
 
-efault_end:
-       user_write_access_end();
 efault:
        buf->error = -EFAULT;
        return false;
@@ -458,16 +447,13 @@ static bool compat_fillonedir(struct dir_context *ctx, const char *name,
        }
        buf->result++;
        dirent = buf->dirent;
-       if (!user_write_access_begin(dirent, dirent_size(dirent, namlen + 1)))
-               goto efault;
-       unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
-       unsafe_put_user(offset, &dirent->d_offset, efault_end);
-       unsafe_put_user(namlen, &dirent->d_namlen, efault_end);
-       unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
-       user_write_access_end();
+       scoped_user_write_access_size(dirent, dirent_size(dirent, namlen + 1), efault) {
+               unsafe_put_user(d_ino, &dirent->d_ino, efault);
+               unsafe_put_user(offset, &dirent->d_offset, efault);
+               unsafe_put_user(namlen, &dirent->d_namlen, efault);
+               unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+       }
        return true;
-efault_end:
-       user_write_access_end();
 efault:
        buf->result = -EFAULT;
        return false;
@@ -538,22 +524,18 @@ static bool compat_filldir(struct dir_context *ctx, const char *name, int namlen
                return false;
        dirent = buf->current_dir;
        prev = (void __user *) dirent - prev_reclen;
-       if (!user_write_access_begin(prev, reclen + prev_reclen))
-               goto efault;
-
-       unsafe_put_user(offset, &prev->d_off, efault_end);
-       unsafe_put_user(d_ino, &dirent->d_ino, efault_end);
-       unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
-       unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
-       unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
-       user_write_access_end();
+       scoped_user_write_access_size(prev, reclen + prev_reclen, efault) {
+               unsafe_put_user(offset, &prev->d_off, efault);
+               unsafe_put_user(d_ino, &dirent->d_ino, efault);
+               unsafe_put_user(reclen, &dirent->d_reclen, efault);
+               unsafe_put_user(d_type, (char __user *)dirent + reclen - 1, efault);
+               unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault);
+       }
 
        buf->prev_reclen = reclen;
        buf->current_dir = (void __user *)dirent + reclen;
        ctx->count -= reclen;
        return true;
-efault_end:
-       user_write_access_end();
 efault:
        buf->error = -EFAULT;
        return false;
index 78a1508c84d3d7a0a78d7b21058e1f4d3912772c..eef27707f91226adf7e82a04b4bd6b01527a5bae 100644 (file)
@@ -1005,17 +1005,17 @@ static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,
        fdcount = do_poll(head, &table, end_time);
        poll_freewait(&table);
 
-       if (!user_write_access_begin(ufds, nfds * sizeof(*ufds)))
-               goto out_fds;
+       scoped_user_write_access_size(ufds, nfds * sizeof(*ufds), out_fds) {
+               struct pollfd __user *_ufds = ufds;
 
-       for (walk = head; walk; walk = walk->next) {
-               struct pollfd *fds = walk->entries;
-               unsigned int j;
+               for (walk = head; walk; walk = walk->next) {
+                       struct pollfd *fds = walk->entries;
+                       unsigned int j;
 
-               for (j = walk->len; j; fds++, ufds++, j--)
-                       unsafe_put_user(fds->revents, &ufds->revents, Efault);
-       }
-       user_write_access_end();
+                       for (j = walk->len; j; fds++, _ufds++, j--)
+                               unsafe_put_user(fds->revents, &_ufds->revents, out_fds);
+               }
+       }
 
        err = fdcount;
 out_fds:
@@ -1027,11 +1027,6 @@ out_fds:
        }
 
        return err;
-
-Efault:
-       user_write_access_end();
-       err = -EFAULT;
-       goto out_fds;
 }
 
 static long do_restart_poll(struct restart_block *restart_block)
@@ -1339,15 +1334,13 @@ static inline int get_compat_sigset_argpack(struct compat_sigset_argpack *to,
                                            struct compat_sigset_argpack __user *from)
 {
        if (from) {
-               if (!user_read_access_begin(from, sizeof(*from)))
-                       return -EFAULT;
-               unsafe_get_user(to->p, &from->p, Efault);
-               unsafe_get_user(to->size, &from->size, Efault);
-               user_read_access_end();
+               scoped_user_read_access(from, efault) {
+                       unsafe_get_user(to->p, &from->p, efault);
+                       unsafe_get_user(to->size, &from->size, efault);
+               }
        }
        return 0;
-Efault:
-       user_read_access_end();
+efault:
        return -EFAULT;
 }