LCOV - code coverage report
Current view: top level - kernel - umh.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 16 166 9.6 %
Date: 2023-08-24 13:40:31 Functions: 3 15 20.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  * umh - the kernel usermode helper
       4             :  */
       5             : #include <linux/module.h>
       6             : #include <linux/sched.h>
       7             : #include <linux/sched/task.h>
       8             : #include <linux/binfmts.h>
       9             : #include <linux/syscalls.h>
      10             : #include <linux/unistd.h>
      11             : #include <linux/kmod.h>
      12             : #include <linux/slab.h>
      13             : #include <linux/completion.h>
      14             : #include <linux/cred.h>
      15             : #include <linux/file.h>
      16             : #include <linux/fdtable.h>
      17             : #include <linux/fs_struct.h>
      18             : #include <linux/workqueue.h>
      19             : #include <linux/security.h>
      20             : #include <linux/mount.h>
      21             : #include <linux/kernel.h>
      22             : #include <linux/init.h>
      23             : #include <linux/resource.h>
      24             : #include <linux/notifier.h>
      25             : #include <linux/suspend.h>
      26             : #include <linux/rwsem.h>
      27             : #include <linux/ptrace.h>
      28             : #include <linux/async.h>
      29             : #include <linux/uaccess.h>
      30             : #include <linux/initrd.h>
      31             : #include <linux/freezer.h>
      32             : 
      33             : #include <trace/events/module.h>
      34             : 
      35             : static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
      36             : static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
      37             : static DEFINE_SPINLOCK(umh_sysctl_lock);
      38             : static DECLARE_RWSEM(umhelper_sem);
      39             : 
      40             : static void call_usermodehelper_freeinfo(struct subprocess_info *info)
      41             : {
      42           0 :         if (info->cleanup)
      43           0 :                 (*info->cleanup)(info);
      44           0 :         kfree(info);
      45             : }
      46             : 
      47           0 : static void umh_complete(struct subprocess_info *sub_info)
      48             : {
      49           0 :         struct completion *comp = xchg(&sub_info->complete, NULL);
      50             :         /*
      51             :          * See call_usermodehelper_exec(). If xchg() returns NULL
      52             :          * we own sub_info, the UMH_KILLABLE caller has gone away
      53             :          * or the caller used UMH_NO_WAIT.
      54             :          */
      55           0 :         if (comp)
      56           0 :                 complete(comp);
      57             :         else
      58             :                 call_usermodehelper_freeinfo(sub_info);
      59           0 : }
      60             : 
      61             : /*
      62             :  * This is the task which runs the usermode application
      63             :  */
      64           0 : static int call_usermodehelper_exec_async(void *data)
      65             : {
      66           0 :         struct subprocess_info *sub_info = data;
      67             :         struct cred *new;
      68             :         int retval;
      69             : 
      70           0 :         spin_lock_irq(&current->sighand->siglock);
      71           0 :         flush_signal_handlers(current, 1);
      72           0 :         spin_unlock_irq(&current->sighand->siglock);
      73             : 
      74             :         /*
      75             :          * Initial kernel threads share ther FS with init, in order to
      76             :          * get the init root directory. But we've now created a new
      77             :          * thread that is going to execve a user process and has its own
      78             :          * 'struct fs_struct'. Reset umask to the default.
      79             :          */
      80           0 :         current->fs->umask = 0022;
      81             : 
      82             :         /*
      83             :          * Our parent (unbound workqueue) runs with elevated scheduling
      84             :          * priority. Avoid propagating that into the userspace child.
      85             :          */
      86           0 :         set_user_nice(current, 0);
      87             : 
      88           0 :         retval = -ENOMEM;
      89           0 :         new = prepare_kernel_cred(current);
      90           0 :         if (!new)
      91             :                 goto out;
      92             : 
      93           0 :         spin_lock(&umh_sysctl_lock);
      94           0 :         new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset);
      95           0 :         new->cap_inheritable = cap_intersect(usermodehelper_inheritable,
      96             :                                              new->cap_inheritable);
      97           0 :         spin_unlock(&umh_sysctl_lock);
      98             : 
      99           0 :         if (sub_info->init) {
     100           0 :                 retval = sub_info->init(sub_info, new);
     101           0 :                 if (retval) {
     102           0 :                         abort_creds(new);
     103           0 :                         goto out;
     104             :                 }
     105             :         }
     106             : 
     107           0 :         commit_creds(new);
     108             : 
     109             :         wait_for_initramfs();
     110           0 :         retval = kernel_execve(sub_info->path,
     111           0 :                                (const char *const *)sub_info->argv,
     112           0 :                                (const char *const *)sub_info->envp);
     113             : out:
     114           0 :         sub_info->retval = retval;
     115             :         /*
     116             :          * call_usermodehelper_exec_sync() will call umh_complete
     117             :          * if UHM_WAIT_PROC.
     118             :          */
     119           0 :         if (!(sub_info->wait & UMH_WAIT_PROC))
     120           0 :                 umh_complete(sub_info);
     121           0 :         if (!retval)
     122           0 :                 return 0;
     123           0 :         do_exit(0);
     124             : }
     125             : 
     126             : /* Handles UMH_WAIT_PROC.  */
     127           0 : static void call_usermodehelper_exec_sync(struct subprocess_info *sub_info)
     128             : {
     129             :         pid_t pid;
     130             : 
     131             :         /* If SIGCLD is ignored do_wait won't populate the status. */
     132           0 :         kernel_sigaction(SIGCHLD, SIG_DFL);
     133           0 :         pid = user_mode_thread(call_usermodehelper_exec_async, sub_info, SIGCHLD);
     134           0 :         if (pid < 0)
     135           0 :                 sub_info->retval = pid;
     136             :         else
     137           0 :                 kernel_wait(pid, &sub_info->retval);
     138             : 
     139             :         /* Restore default kernel sig handler */
     140           0 :         kernel_sigaction(SIGCHLD, SIG_IGN);
     141           0 :         umh_complete(sub_info);
     142           0 : }
     143             : 
     144             : /*
     145             :  * We need to create the usermodehelper kernel thread from a task that is affine
     146             :  * to an optimized set of CPUs (or nohz housekeeping ones) such that they
     147             :  * inherit a widest affinity irrespective of call_usermodehelper() callers with
     148             :  * possibly reduced affinity (eg: per-cpu workqueues). We don't want
     149             :  * usermodehelper targets to contend a busy CPU.
     150             :  *
     151             :  * Unbound workqueues provide such wide affinity and allow to block on
     152             :  * UMH_WAIT_PROC requests without blocking pending request (up to some limit).
     153             :  *
     154             :  * Besides, workqueues provide the privilege level that caller might not have
     155             :  * to perform the usermodehelper request.
     156             :  *
     157             :  */
     158           0 : static void call_usermodehelper_exec_work(struct work_struct *work)
     159             : {
     160           0 :         struct subprocess_info *sub_info =
     161           0 :                 container_of(work, struct subprocess_info, work);
     162             : 
     163           0 :         if (sub_info->wait & UMH_WAIT_PROC) {
     164           0 :                 call_usermodehelper_exec_sync(sub_info);
     165             :         } else {
     166             :                 pid_t pid;
     167             :                 /*
     168             :                  * Use CLONE_PARENT to reparent it to kthreadd; we do not
     169             :                  * want to pollute current->children, and we need a parent
     170             :                  * that always ignores SIGCHLD to ensure auto-reaping.
     171             :                  */
     172           0 :                 pid = user_mode_thread(call_usermodehelper_exec_async, sub_info,
     173             :                                        CLONE_PARENT | SIGCHLD);
     174           0 :                 if (pid < 0) {
     175           0 :                         sub_info->retval = pid;
     176           0 :                         umh_complete(sub_info);
     177             :                 }
     178             :         }
     179           0 : }
     180             : 
     181             : /*
     182             :  * If set, call_usermodehelper_exec() will exit immediately returning -EBUSY
     183             :  * (used for preventing user land processes from being created after the user
     184             :  * land has been frozen during a system-wide hibernation or suspend operation).
     185             :  * Should always be manipulated under umhelper_sem acquired for write.
     186             :  */
     187             : static enum umh_disable_depth usermodehelper_disabled = UMH_DISABLED;
     188             : 
     189             : /* Number of helpers running */
     190             : static atomic_t running_helpers = ATOMIC_INIT(0);
     191             : 
     192             : /*
     193             :  * Wait queue head used by usermodehelper_disable() to wait for all running
     194             :  * helpers to finish.
     195             :  */
     196             : static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq);
     197             : 
     198             : /*
     199             :  * Used by usermodehelper_read_lock_wait() to wait for usermodehelper_disabled
     200             :  * to become 'false'.
     201             :  */
     202             : static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq);
     203             : 
     204             : /*
     205             :  * Time to wait for running_helpers to become zero before the setting of
     206             :  * usermodehelper_disabled in usermodehelper_disable() fails
     207             :  */
     208             : #define RUNNING_HELPERS_TIMEOUT (5 * HZ)
     209             : 
     210           0 : int usermodehelper_read_trylock(void)
     211             : {
     212           0 :         DEFINE_WAIT(wait);
     213           0 :         int ret = 0;
     214             : 
     215           0 :         down_read(&umhelper_sem);
     216             :         for (;;) {
     217           0 :                 prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
     218             :                                 TASK_INTERRUPTIBLE);
     219           0 :                 if (!usermodehelper_disabled)
     220             :                         break;
     221             : 
     222           0 :                 if (usermodehelper_disabled == UMH_DISABLED)
     223           0 :                         ret = -EAGAIN;
     224             : 
     225           0 :                 up_read(&umhelper_sem);
     226             : 
     227           0 :                 if (ret)
     228             :                         break;
     229             : 
     230           0 :                 schedule();
     231           0 :                 try_to_freeze();
     232             : 
     233           0 :                 down_read(&umhelper_sem);
     234             :         }
     235           0 :         finish_wait(&usermodehelper_disabled_waitq, &wait);
     236           0 :         return ret;
     237             : }
     238             : EXPORT_SYMBOL_GPL(usermodehelper_read_trylock);
     239             : 
     240           0 : long usermodehelper_read_lock_wait(long timeout)
     241             : {
     242           0 :         DEFINE_WAIT(wait);
     243             : 
     244           0 :         if (timeout < 0)
     245             :                 return -EINVAL;
     246             : 
     247           0 :         down_read(&umhelper_sem);
     248             :         for (;;) {
     249           0 :                 prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
     250             :                                 TASK_UNINTERRUPTIBLE);
     251           0 :                 if (!usermodehelper_disabled)
     252             :                         break;
     253             : 
     254           0 :                 up_read(&umhelper_sem);
     255             : 
     256           0 :                 timeout = schedule_timeout(timeout);
     257           0 :                 if (!timeout)
     258             :                         break;
     259             : 
     260           0 :                 down_read(&umhelper_sem);
     261             :         }
     262           0 :         finish_wait(&usermodehelper_disabled_waitq, &wait);
     263           0 :         return timeout;
     264             : }
     265             : EXPORT_SYMBOL_GPL(usermodehelper_read_lock_wait);
     266             : 
     267           0 : void usermodehelper_read_unlock(void)
     268             : {
     269           0 :         up_read(&umhelper_sem);
     270           0 : }
     271             : EXPORT_SYMBOL_GPL(usermodehelper_read_unlock);
     272             : 
     273             : /**
     274             :  * __usermodehelper_set_disable_depth - Modify usermodehelper_disabled.
     275             :  * @depth: New value to assign to usermodehelper_disabled.
     276             :  *
     277             :  * Change the value of usermodehelper_disabled (under umhelper_sem locked for
     278             :  * writing) and wakeup tasks waiting for it to change.
     279             :  */
     280           1 : void __usermodehelper_set_disable_depth(enum umh_disable_depth depth)
     281             : {
     282           1 :         down_write(&umhelper_sem);
     283           1 :         usermodehelper_disabled = depth;
     284           1 :         wake_up(&usermodehelper_disabled_waitq);
     285           1 :         up_write(&umhelper_sem);
     286           1 : }
     287             : 
     288             : /**
     289             :  * __usermodehelper_disable - Prevent new helpers from being started.
     290             :  * @depth: New value to assign to usermodehelper_disabled.
     291             :  *
     292             :  * Set usermodehelper_disabled to @depth and wait for running helpers to exit.
     293             :  */
     294           1 : int __usermodehelper_disable(enum umh_disable_depth depth)
     295             : {
     296             :         long retval;
     297             : 
     298           1 :         if (!depth)
     299             :                 return -EINVAL;
     300             : 
     301           1 :         down_write(&umhelper_sem);
     302           1 :         usermodehelper_disabled = depth;
     303           1 :         up_write(&umhelper_sem);
     304             : 
     305             :         /*
     306             :          * From now on call_usermodehelper_exec() won't start any new
     307             :          * helpers, so it is sufficient if running_helpers turns out to
     308             :          * be zero at one point (it may be increased later, but that
     309             :          * doesn't matter).
     310             :          */
     311           2 :         retval = wait_event_timeout(running_helpers_waitq,
     312             :                                         atomic_read(&running_helpers) == 0,
     313             :                                         RUNNING_HELPERS_TIMEOUT);
     314           1 :         if (retval)
     315             :                 return 0;
     316             : 
     317           0 :         __usermodehelper_set_disable_depth(UMH_ENABLED);
     318           0 :         return -EAGAIN;
     319             : }
     320             : 
     321             : static void helper_lock(void)
     322             : {
     323           0 :         atomic_inc(&running_helpers);
     324           0 :         smp_mb__after_atomic();
     325             : }
     326             : 
     327           0 : static void helper_unlock(void)
     328             : {
     329           0 :         if (atomic_dec_and_test(&running_helpers))
     330           0 :                 wake_up(&running_helpers_waitq);
     331           0 : }
     332             : 
     333             : /**
     334             :  * call_usermodehelper_setup - prepare to call a usermode helper
     335             :  * @path: path to usermode executable
     336             :  * @argv: arg vector for process
     337             :  * @envp: environment for process
     338             :  * @gfp_mask: gfp mask for memory allocation
     339             :  * @init: an init function
     340             :  * @cleanup: a cleanup function
     341             :  * @data: arbitrary context sensitive data
     342             :  *
     343             :  * Returns either %NULL on allocation failure, or a subprocess_info
     344             :  * structure.  This should be passed to call_usermodehelper_exec to
     345             :  * exec the process and free the structure.
     346             :  *
     347             :  * The init function is used to customize the helper process prior to
     348             :  * exec.  A non-zero return code causes the process to error out, exit,
     349             :  * and return the failure to the calling process
     350             :  *
     351             :  * The cleanup function is just before the subprocess_info is about to
     352             :  * be freed.  This can be used for freeing the argv and envp.  The
     353             :  * Function must be runnable in either a process context or the
     354             :  * context in which call_usermodehelper_exec is called.
     355             :  */
     356           0 : struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv,
     357             :                 char **envp, gfp_t gfp_mask,
     358             :                 int (*init)(struct subprocess_info *info, struct cred *new),
     359             :                 void (*cleanup)(struct subprocess_info *info),
     360             :                 void *data)
     361             : {
     362             :         struct subprocess_info *sub_info;
     363           0 :         sub_info = kzalloc(sizeof(struct subprocess_info), gfp_mask);
     364           0 :         if (!sub_info)
     365             :                 goto out;
     366             : 
     367           0 :         INIT_WORK(&sub_info->work, call_usermodehelper_exec_work);
     368             : 
     369             : #ifdef CONFIG_STATIC_USERMODEHELPER
     370             :         sub_info->path = CONFIG_STATIC_USERMODEHELPER_PATH;
     371             : #else
     372           0 :         sub_info->path = path;
     373             : #endif
     374           0 :         sub_info->argv = argv;
     375           0 :         sub_info->envp = envp;
     376             : 
     377           0 :         sub_info->cleanup = cleanup;
     378           0 :         sub_info->init = init;
     379           0 :         sub_info->data = data;
     380             :   out:
     381           0 :         return sub_info;
     382             : }
     383             : EXPORT_SYMBOL(call_usermodehelper_setup);
     384             : 
     385             : /**
     386             :  * call_usermodehelper_exec - start a usermode application
     387             :  * @sub_info: information about the subprocess
     388             :  * @wait: wait for the application to finish and return status.
     389             :  *        when UMH_NO_WAIT don't wait at all, but you get no useful error back
     390             :  *        when the program couldn't be exec'ed. This makes it safe to call
     391             :  *        from interrupt context.
     392             :  *
     393             :  * Runs a user-space application.  The application is started
     394             :  * asynchronously if wait is not set, and runs as a child of system workqueues.
     395             :  * (ie. it runs with full root capabilities and optimized affinity).
     396             :  *
     397             :  * Note: successful return value does not guarantee the helper was called at
     398             :  * all. You can't rely on sub_info->{init,cleanup} being called even for
     399             :  * UMH_WAIT_* wait modes as STATIC_USERMODEHELPER_PATH="" turns all helpers
     400             :  * into a successful no-op.
     401             :  */
     402           0 : int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
     403             : {
     404           0 :         unsigned int state = TASK_UNINTERRUPTIBLE;
     405           0 :         DECLARE_COMPLETION_ONSTACK(done);
     406           0 :         int retval = 0;
     407             : 
     408           0 :         if (!sub_info->path) {
     409           0 :                 call_usermodehelper_freeinfo(sub_info);
     410           0 :                 return -EINVAL;
     411             :         }
     412             :         helper_lock();
     413           0 :         if (usermodehelper_disabled) {
     414             :                 retval = -EBUSY;
     415             :                 goto out;
     416             :         }
     417             : 
     418             :         /*
     419             :          * If there is no binary for us to call, then just return and get out of
     420             :          * here.  This allows us to set STATIC_USERMODEHELPER_PATH to "" and
     421             :          * disable all call_usermodehelper() calls.
     422             :          */
     423           0 :         if (strlen(sub_info->path) == 0)
     424             :                 goto out;
     425             : 
     426             :         /*
     427             :          * Set the completion pointer only if there is a waiter.
     428             :          * This makes it possible to use umh_complete to free
     429             :          * the data structure in case of UMH_NO_WAIT.
     430             :          */
     431           0 :         sub_info->complete = (wait == UMH_NO_WAIT) ? NULL : &done;
     432           0 :         sub_info->wait = wait;
     433             : 
     434           0 :         queue_work(system_unbound_wq, &sub_info->work);
     435           0 :         if (wait == UMH_NO_WAIT)        /* task has freed sub_info */
     436             :                 goto unlock;
     437             : 
     438           0 :         if (wait & UMH_FREEZABLE)
     439           0 :                 state |= TASK_FREEZABLE;
     440             : 
     441           0 :         if (wait & UMH_KILLABLE) {
     442           0 :                 retval = wait_for_completion_state(&done, state | TASK_KILLABLE);
     443           0 :                 if (!retval)
     444             :                         goto wait_done;
     445             : 
     446             :                 /* umh_complete() will see NULL and free sub_info */
     447           0 :                 if (xchg(&sub_info->complete, NULL))
     448             :                         goto unlock;
     449             : 
     450             :                 /*
     451             :                  * fallthrough; in case of -ERESTARTSYS now do uninterruptible
     452             :                  * wait_for_completion_state(). Since umh_complete() shall call
     453             :                  * complete() in a moment if xchg() above returned NULL, this
     454             :                  * uninterruptible wait_for_completion_state() will not block
     455             :                  * SIGKILL'ed processes for long.
     456             :                  */
     457             :         }
     458           0 :         wait_for_completion_state(&done, state);
     459             : 
     460             : wait_done:
     461           0 :         retval = sub_info->retval;
     462             : out:
     463             :         call_usermodehelper_freeinfo(sub_info);
     464             : unlock:
     465           0 :         helper_unlock();
     466           0 :         return retval;
     467             : }
     468             : EXPORT_SYMBOL(call_usermodehelper_exec);
     469             : 
     470             : /**
     471             :  * call_usermodehelper() - prepare and start a usermode application
     472             :  * @path: path to usermode executable
     473             :  * @argv: arg vector for process
     474             :  * @envp: environment for process
     475             :  * @wait: wait for the application to finish and return status.
     476             :  *        when UMH_NO_WAIT don't wait at all, but you get no useful error back
     477             :  *        when the program couldn't be exec'ed. This makes it safe to call
     478             :  *        from interrupt context.
     479             :  *
     480             :  * This function is the equivalent to use call_usermodehelper_setup() and
     481             :  * call_usermodehelper_exec().
     482             :  */
     483           0 : int call_usermodehelper(const char *path, char **argv, char **envp, int wait)
     484             : {
     485             :         struct subprocess_info *info;
     486           0 :         gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
     487             : 
     488           0 :         info = call_usermodehelper_setup(path, argv, envp, gfp_mask,
     489             :                                          NULL, NULL, NULL);
     490           0 :         if (info == NULL)
     491             :                 return -ENOMEM;
     492             : 
     493           0 :         return call_usermodehelper_exec(info, wait);
     494             : }
     495             : EXPORT_SYMBOL(call_usermodehelper);
     496             : 
     497             : #if defined(CONFIG_SYSCTL)
     498           0 : static int proc_cap_handler(struct ctl_table *table, int write,
     499             :                          void *buffer, size_t *lenp, loff_t *ppos)
     500             : {
     501             :         struct ctl_table t;
     502             :         unsigned long cap_array[2];
     503             :         kernel_cap_t new_cap, *cap;
     504             :         int err;
     505             : 
     506           0 :         if (write && (!capable(CAP_SETPCAP) ||
     507           0 :                       !capable(CAP_SYS_MODULE)))
     508             :                 return -EPERM;
     509             : 
     510             :         /*
     511             :          * convert from the global kernel_cap_t to the ulong array to print to
     512             :          * userspace if this is a read.
     513             :          *
     514             :          * Legacy format: capabilities are exposed as two 32-bit values
     515             :          */
     516           0 :         cap = table->data;
     517           0 :         spin_lock(&umh_sysctl_lock);
     518           0 :         cap_array[0] = (u32) cap->val;
     519           0 :         cap_array[1] = cap->val >> 32;
     520           0 :         spin_unlock(&umh_sysctl_lock);
     521             : 
     522           0 :         t = *table;
     523           0 :         t.data = &cap_array;
     524             : 
     525             :         /*
     526             :          * actually read or write and array of ulongs from userspace.  Remember
     527             :          * these are least significant 32 bits first
     528             :          */
     529           0 :         err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
     530           0 :         if (err < 0)
     531             :                 return err;
     532             : 
     533           0 :         new_cap.val = (u32)cap_array[0];
     534           0 :         new_cap.val += (u64)cap_array[1] << 32;
     535             : 
     536             :         /*
     537             :          * Drop everything not in the new_cap (but don't add things)
     538             :          */
     539           0 :         if (write) {
     540           0 :                 spin_lock(&umh_sysctl_lock);
     541           0 :                 *cap = cap_intersect(*cap, new_cap);
     542             :                 spin_unlock(&umh_sysctl_lock);
     543             :         }
     544             : 
     545             :         return 0;
     546             : }
     547             : 
     548             : static struct ctl_table usermodehelper_table[] = {
     549             :         {
     550             :                 .procname       = "bset",
     551             :                 .data           = &usermodehelper_bset,
     552             :                 .maxlen         = 2 * sizeof(unsigned long),
     553             :                 .mode           = 0600,
     554             :                 .proc_handler   = proc_cap_handler,
     555             :         },
     556             :         {
     557             :                 .procname       = "inheritable",
     558             :                 .data           = &usermodehelper_inheritable,
     559             :                 .maxlen         = 2 * sizeof(unsigned long),
     560             :                 .mode           = 0600,
     561             :                 .proc_handler   = proc_cap_handler,
     562             :         },
     563             :         { }
     564             : };
     565             : 
     566           1 : static int __init init_umh_sysctls(void)
     567             : {
     568           1 :         register_sysctl_init("kernel/usermodehelper", usermodehelper_table);
     569           1 :         return 0;
     570             : }
     571             : early_initcall(init_umh_sysctls);
     572             : #endif /* CONFIG_SYSCTL */

Generated by: LCOV version 1.14