Allow CLOSE_RANGE actions to pass newfd == -1 to mean the largest
possible fd. This gives userspace a compact way to request the common
close_range(first, ~0U, flags) pattern even though the UAPI action uses
signed fd fields so OPEN actions can still carry AT_FDCWD.

Signed-off-by: Li Chen <[email protected]>
---
 Documentation/userspace-api/spawn_template.rst |  3 ++-
 fs/spawn_template.c                            | 10 +++++++---
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/Documentation/userspace-api/spawn_template.rst 
b/Documentation/userspace-api/spawn_template.rst
index afe215e51db6f..be66be20d4fde 100644
--- a/Documentation/userspace-api/spawn_template.rst
+++ b/Documentation/userspace-api/spawn_template.rst
@@ -86,7 +86,8 @@ kind of setup that ``posix_spawn_file_actions_t`` commonly 
performs:
   Open a path using ``struct open_how`` and install it at ``newfd``.
 
 ``SPAWN_TEMPLATE_ACTION_CLOSE_RANGE``
-  Apply ``close_range()`` to a child fd range.
+  Apply ``close_range()`` to a child fd range.  Passing ``newfd == -1`` means
+  the range extends to the largest possible fd.
 
 ``SPAWN_TEMPLATE_ACTION_SIGMASK``
   Set the child signal mask.
diff --git a/fs/spawn_template.c b/fs/spawn_template.c
index 6430a6645fb57..82b833bc9865a 100644
--- a/fs/spawn_template.c
+++ b/fs/spawn_template.c
@@ -220,6 +220,8 @@ static int spawn_template_apply_sigdefault(const struct 
spawn_template_action *a
 
 static int spawn_template_apply_action(const struct spawn_template_action 
*action)
 {
+       unsigned int max_fd;
+
        switch (action->type) {
        case SPAWN_TEMPLATE_ACTION_CLOSE:
                return close_fd(action->fd);
@@ -251,7 +253,8 @@ static int spawn_template_apply_action(const struct 
spawn_template_action *actio
        case SPAWN_TEMPLATE_ACTION_OPEN:
                return spawn_template_apply_open(action);
        case SPAWN_TEMPLATE_ACTION_CLOSE_RANGE:
-               return do_close_range(action->fd, action->newfd, action->flags);
+               max_fd = action->newfd == -1 ? ~0U : action->newfd;
+               return do_close_range(action->fd, max_fd, action->flags);
        case SPAWN_TEMPLATE_ACTION_SIGMASK:
                return spawn_template_apply_sigmask(action);
        case SPAWN_TEMPLATE_ACTION_SIGDEFAULT:
@@ -306,8 +309,9 @@ static int spawn_template_copy_actions(struct 
spawn_template_action **out_action
                                return -EINVAL;
                        break;
                case SPAWN_TEMPLATE_ACTION_CLOSE_RANGE:
-                       if (actions[i].fd < 0 || actions[i].newfd < 0 ||
-                           actions[i].fd > actions[i].newfd ||
+                       if (actions[i].fd < 0 || actions[i].newfd < -1 ||
+                           (actions[i].newfd >= 0 &&
+                            actions[i].fd > actions[i].newfd) ||
                            (actions[i].flags &
                             ~(CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC)) ||
                            actions[i].arg)
-- 
2.52.0


Reply via email to