Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
ac94a58a
Commit
ac94a58a
authored
Feb 18, 2003
by
Anton Blanchard
Browse files
Options
Browse Files
Download
Plain Diff
Merge samba.org:/scratch/anton/linux-2.5
into samba.org:/scratch/anton/sfr
parents
06365c08
c290649e
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
116 additions
and
314 deletions
+116
-314
arch/i386/mach-voyager/voyager_thread.c
arch/i386/mach-voyager/voyager_thread.c
+4
-13
drivers/acpi/thermal.c
drivers/acpi/thermal.c
+1
-1
drivers/base/hotplug.c
drivers/base/hotplug.c
+1
-1
drivers/bluetooth/bt3c_cs.c
drivers/bluetooth/bt3c_cs.c
+7
-54
drivers/ieee1394/nodemgr.c
drivers/ieee1394/nodemgr.c
+1
-1
drivers/input/input.c
drivers/input/input.c
+1
-1
drivers/isdn/hardware/eicon/divasmain.c
drivers/isdn/hardware/eicon/divasmain.c
+1
-1
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/baycom_epp.c
+6
-39
drivers/pnp/pnpbios/core.c
drivers/pnp/pnpbios/core.c
+1
-1
fs/proc/array.c
fs/proc/array.c
+9
-1
include/linux/kmod.h
include/linux/kmod.h
+2
-2
kernel/compat.c
kernel/compat.c
+3
-2
kernel/kmod.c
kernel/kmod.c
+77
-195
net/bluetooth/hci_core.c
net/bluetooth/hci_core.c
+1
-1
net/core/dev.c
net/core/dev.c
+1
-1
No files found.
arch/i386/mach-voyager/voyager_thread.c
View file @
ac94a58a
...
...
@@ -57,7 +57,7 @@ voyager_thread_start(void)
}
static
int
execute
_helper
(
void
*
string
)
execute
(
const
char
*
string
)
{
int
ret
;
...
...
@@ -74,22 +74,13 @@ execute_helper(void *string)
NULL
,
};
if
((
ret
=
exec_usermodehelper
(
argv
[
0
],
argv
,
envp
))
<
0
)
{
printk
(
KERN_ERR
"Voyager failed to
execute
\"
%s
\"
\n
"
,
(
char
*
)
string
);
if
((
ret
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
,
1
))
!=
0
)
{
printk
(
KERN_ERR
"Voyager failed to
run
\"
%s
\"
: %i
\n
"
,
string
,
ret
);
}
return
ret
;
}
static
void
execute
(
char
*
string
)
{
if
(
kernel_thread
(
execute_helper
,
(
void
*
)
string
,
CLONE_VFORK
|
SIGCHLD
)
<
0
)
{
printk
(
KERN_ERR
"Voyager failed to fork before exec of
\"
%s
\"\n
"
,
string
);
}
}
static
void
check_from_kernel
(
void
)
{
...
...
drivers/acpi/thermal.c
View file @
ac94a58a
...
...
@@ -436,7 +436,7 @@ acpi_thermal_call_usermode (
envp
[
0
]
=
"HOME=/"
;
envp
[
1
]
=
"PATH=/sbin:/bin:/usr/sbin:/usr/bin"
;
call_usermodehelper
(
argv
[
0
],
argv
,
envp
);
call_usermodehelper
(
argv
[
0
],
argv
,
envp
,
0
);
return_VALUE
(
0
);
}
...
...
drivers/base/hotplug.c
View file @
ac94a58a
...
...
@@ -114,7 +114,7 @@ static int do_hotplug (struct device *dev, char *argv1, const char *action,
pr_debug
(
"%s: %s %s %s %s %s %s
\n
"
,
__FUNCTION__
,
argv
[
0
],
argv
[
1
],
envp
[
0
],
envp
[
1
],
envp
[
2
],
envp
[
3
]);
retval
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
);
retval
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
,
0
);
if
(
retval
)
pr_debug
(
"%s - call_usermodehelper returned %d
\n
"
,
__FUNCTION__
,
retval
);
...
...
drivers/bluetooth/bt3c_cs.c
View file @
ac94a58a
...
...
@@ -24,18 +24,14 @@
#include <linux/config.h>
#include <linux/module.h>
#define __KERNEL_SYSCALLS__
#include <linux/kernel.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/spinlock.h>
...
...
@@ -405,7 +401,6 @@ void bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
/* ======================== HCI interface ======================== */
...
...
@@ -489,65 +484,23 @@ static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long
#define FW_LOADER "/sbin/bluefw"
static
int
errno
;
static
int
bt3c_fw_loader_exec
(
void
*
dev
)
{
char
*
argv
[]
=
{
FW_LOADER
,
"pccard"
,
dev
,
NULL
};
char
*
envp
[]
=
{
"HOME=/"
,
"TERM=linux"
,
"PATH=/sbin:/usr/sbin:/bin:/usr/bin"
,
NULL
};
int
err
;
err
=
exec_usermodehelper
(
FW_LOADER
,
argv
,
envp
);
if
(
err
)
printk
(
KERN_WARNING
"bt3c_cs: Failed to exec
\"
%s pccard %s
\"
.
\n
"
,
FW_LOADER
,
(
char
*
)
dev
);
return
err
;
}
static
int
bt3c_firmware_load
(
bt3c_info_t
*
info
)
{
sigset_t
tmpsig
;
char
dev
[
16
];
pid_t
pid
;
int
result
;
int
err
;
/* Check if root fs is mounted */
if
(
!
current
->
fs
->
root
)
{
printk
(
KERN_WARNING
"bt3c_cs: Root filesystem is not mounted.
\n
"
);
return
-
EPERM
;
}
char
*
argv
[]
=
{
FW_LOADER
,
"pccard"
,
dev
,
NULL
};
char
*
envp
[]
=
{
"HOME=/"
,
"TERM=linux"
,
"PATH=/sbin:/usr/sbin:/bin:/usr/bin"
,
NULL
};
sprintf
(
dev
,
"%04x"
,
info
->
link
.
io
.
BasePort1
);
pid
=
kernel_thread
(
bt3c_fw_loader_exec
,
(
void
*
)
dev
,
0
);
if
(
pid
<
0
)
{
printk
(
KERN_WARNING
"bt3c_cs: Forking of kernel thread failed (errno=%d).
\n
"
,
-
pid
);
return
pid
;
}
/* Block signals, everything but SIGKILL/SIGSTOP */
spin_lock_irq
(
&
current
->
sighand
->
siglock
);
tmpsig
=
current
->
blocked
;
siginitsetinv
(
&
current
->
blocked
,
sigmask
(
SIGKILL
)
|
sigmask
(
SIGSTOP
));
recalc_sigpending
();
spin_unlock_irq
(
&
current
->
sighand
->
siglock
);
result
=
waitpid
(
pid
,
NULL
,
__WCLONE
);
/* Allow signals again */
spin_lock_irq
(
&
current
->
sighand
->
siglock
);
current
->
blocked
=
tmpsig
;
recalc_sigpending
();
spin_unlock_irq
(
&
current
->
sighand
->
siglock
);
if
(
result
!=
pid
)
{
printk
(
KERN_WARNING
"bt3c_cs: Waiting for pid %d failed (errno=%d).
\n
"
,
pid
,
-
result
);
return
-
result
;
}
err
=
call_usermodehelper
(
FW_LOADER
,
argv
,
envp
,
1
);
if
(
err
)
printk
(
KERN_WARNING
"bt3c_cs: Failed to run
\"
%s pccard %s
\"
(errno=%d).
\n
"
,
FW_LOADER
,
dev
,
err
);
return
0
;
return
err
;
}
...
...
drivers/ieee1394/nodemgr.c
View file @
ac94a58a
...
...
@@ -786,7 +786,7 @@ static void nodemgr_call_policy(char *verb, struct unit_directory *ud)
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
HPSB_DEBUG
(
"NodeMgr: %s %s %016Lx"
,
argv
[
0
],
verb
,
(
long
long
unsigned
)
ud
->
ne
->
guid
);
#endif
value
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
);
value
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
,
0
);
kfree
(
buf
);
kfree
(
envp
);
if
(
value
!=
0
)
...
...
drivers/input/input.c
View file @
ac94a58a
...
...
@@ -383,7 +383,7 @@ static void input_call_hotplug(char *verb, struct input_dev *dev)
argv
[
0
],
argv
[
1
],
envp
[
0
],
envp
[
1
],
envp
[
2
],
envp
[
3
],
envp
[
4
]);
#endif
value
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
);
value
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
,
0
);
kfree
(
buf
);
kfree
(
envp
);
...
...
drivers/isdn/hardware/eicon/divasmain.c
View file @
ac94a58a
...
...
@@ -263,7 +263,7 @@ static void diva_adapter_trapped(void *context)
pdpc
->
card_failed
=
0
;
argv
[
2
]
=
&
adapter
[
0
];
ret
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
);
ret
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
,
0
);
if
(
ret
)
{
printk
(
KERN_ERR
...
...
drivers/net/hamradio/baycom_epp.c
View file @
ac94a58a
...
...
@@ -369,15 +369,14 @@ static char eppconfig_path[256] = "/usr/sbin/eppfpga";
static
char
*
envp
[]
=
{
"HOME=/"
,
"TERM=linux"
,
"PATH=/usr/bin:/bin"
,
NULL
};
static
int
errno
;
static
int
exec_eppfpga
(
void
*
b
)
/* eppconfig: called during ifconfig up to configure the modem */
static
int
eppconfig
(
struct
baycom_state
*
bc
)
{
struct
baycom_state
*
bc
=
(
struct
baycom_state
*
)
b
;
char
modearg
[
256
];
char
portarg
[
16
];
char
*
argv
[]
=
{
eppconfig_path
,
"-s"
,
"-p"
,
portarg
,
"-m"
,
modearg
,
NULL
};
int
i
;
char
*
argv
[]
=
{
eppconfig_path
,
"-s"
,
"-p"
,
portarg
,
"-m"
,
modearg
,
NULL
};
int
ret
;
/* set up arguments */
sprintf
(
modearg
,
"%sclk,%smodem,fclk=%d,bps=%d,divider=%d%s,extstat"
,
...
...
@@ -388,39 +387,7 @@ static int exec_eppfpga(void *b)
sprintf
(
portarg
,
"%ld"
,
bc
->
pdev
->
port
->
base
);
printk
(
KERN_DEBUG
"%s: %s -s -p %s -m %s
\n
"
,
bc_drvname
,
eppconfig_path
,
portarg
,
modearg
);
i
=
exec_usermodehelper
(
eppconfig_path
,
argv
,
envp
);
if
(
i
<
0
)
{
printk
(
KERN_ERR
"%s: failed to exec %s -s -p %s -m %s, errno = %d
\n
"
,
bc_drvname
,
eppconfig_path
,
portarg
,
modearg
,
i
);
return
i
;
}
return
0
;
}
/* eppconfig: called during ifconfig up to configure the modem */
static
int
eppconfig
(
struct
baycom_state
*
bc
)
{
int
i
,
pid
,
r
;
mm_segment_t
fs
;
pid
=
kernel_thread
(
exec_eppfpga
,
bc
,
CLONE_FS
);
if
(
pid
<
0
)
{
printk
(
KERN_ERR
"%s: fork failed, errno %d
\n
"
,
bc_drvname
,
-
pid
);
return
pid
;
}
fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
/* Allow i to be in kernel space. */
r
=
waitpid
(
pid
,
&
i
,
__WCLONE
);
set_fs
(
fs
);
if
(
r
!=
pid
)
{
printk
(
KERN_ERR
"%s: waitpid(%d) failed, returning %d
\n
"
,
bc_drvname
,
pid
,
r
);
return
-
1
;
}
printk
(
KERN_DEBUG
"%s: eppfpga returned %d
\n
"
,
bc_drvname
,
i
);
return
i
;
return
call_usermodehelper
(
eppconfig_path
,
argv
,
envp
,
1
);
}
/* ---------------------------------------------------------------------- */
...
...
drivers/pnp/pnpbios/core.c
View file @
ac94a58a
...
...
@@ -602,7 +602,7 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
info
->
location_id
,
info
->
serial
,
info
->
capabilities
);
envp
[
i
]
=
0
;
value
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
);
value
=
call_usermodehelper
(
argv
[
0
],
argv
,
envp
,
0
);
kfree
(
buf
);
kfree
(
envp
);
return
0
;
...
...
fs/proc/array.c
View file @
ac94a58a
...
...
@@ -316,7 +316,15 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
wchan
=
get_wchan
(
task
);
sigemptyset
(
&
sigign
);
sigemptyset
(
&
sigcatch
);
read_lock
(
&
tasklist_lock
);
if
(
task
->
sighand
)
{
spin_lock_irq
(
&
task
->
sighand
->
siglock
);
collect_sigign_sigcatch
(
task
,
&
sigign
,
&
sigcatch
);
spin_lock_irq
(
&
task
->
sighand
->
siglock
);
}
read_unlock
(
&
tasklist_lock
);
/* scale priority and nice values from timeslices to -20..20 */
/* to make it look like a "normal" Unix priority/nice value */
...
...
include/linux/kmod.h
View file @
ac94a58a
...
...
@@ -21,6 +21,7 @@
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/compiler.h>
#ifdef CONFIG_KMOD
extern
int
request_module
(
const
char
*
name
);
...
...
@@ -29,8 +30,7 @@ static inline int request_module(const char * name) { return -ENOSYS; }
#endif
#define try_then_request_module(x, mod) ((x) ?: request_module(mod), (x))
extern
int
exec_usermodehelper
(
char
*
program_path
,
char
*
argv
[],
char
*
envp
[]);
extern
int
call_usermodehelper
(
char
*
path
,
char
*
argv
[],
char
*
envp
[]);
extern
int
call_usermodehelper
(
char
*
path
,
char
*
argv
[],
char
*
envp
[],
int
wait
);
#ifdef CONFIG_HOTPLUG
extern
char
hotplug_path
[];
...
...
kernel/compat.c
View file @
ac94a58a
...
...
@@ -17,6 +17,7 @@
#include <linux/time.h>
#include <linux/signal.h>
#include <linux/sched.h>
/* for MAX_SCHEDULE_TIMEOUT */
#include <linux/futex.h>
/* for FUTEX_WAIT */
#include <asm/uaccess.h>
...
...
@@ -210,7 +211,7 @@ asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t *set,
return
ret
;
}
extern
long
do_futex
(
u
32
*
,
int
,
int
,
unsigned
long
);
extern
long
do_futex
(
u
nsigned
long
,
int
,
int
,
unsigned
long
);
asmlinkage
long
compat_sys_futex
(
u32
*
uaddr
,
int
op
,
int
val
,
struct
compat_timespec
*
utime
)
...
...
@@ -221,7 +222,7 @@ asmlinkage long compat_sys_futex(u32 *uaddr, int op, int val,
if
((
op
==
FUTEX_WAIT
)
&&
utime
)
{
if
(
get_compat_timespec
(
&
t
,
utime
))
return
-
EFAULT
;
timeout
=
timespec_to_jiffies
(
t
)
+
1
;
timeout
=
timespec_to_jiffies
(
&
t
)
+
1
;
}
return
do_futex
((
unsigned
long
)
uaddr
,
op
,
val
,
timeout
);
}
kernel/kmod.c
View file @
ac94a58a
...
...
@@ -14,8 +14,10 @@
Unblock all signals when we exec a usermode process.
Shuu Yamaguchi <shuu@wondernetworkresources.com> December 2000
*/
call_usermodehelper wait flag, and remove exec_usermodehelper.
Rusty Russell <rusty@rustcorp.com.au> Jan 2003
*/
#define __KERNEL_SYSCALLS__
#include <linux/config.h>
...
...
@@ -31,112 +33,11 @@
#include <linux/workqueue.h>
#include <linux/security.h>
#include <linux/mount.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
extern
int
max_threads
,
system_running
;
static
inline
void
use_init_fs_context
(
void
)
{
struct
fs_struct
*
our_fs
,
*
init_fs
;
struct
dentry
*
root
,
*
pwd
;
struct
vfsmount
*
rootmnt
,
*
pwdmnt
;
struct
namespace
*
our_ns
,
*
init_ns
;
/*
* Make modprobe's fs context be a copy of init's.
*
* We cannot use the user's fs context, because it
* may have a different root than init.
* Since init was created with CLONE_FS, we can grab
* its fs context from "init_task".
*
* The fs context has to be a copy. If it is shared
* with init, then any chdir() call in modprobe will
* also affect init and the other threads sharing
* init_task's fs context.
*
* We created the exec_modprobe thread without CLONE_FS,
* so we can update the fields in our fs context freely.
*/
init_fs
=
init_task
.
fs
;
init_ns
=
init_task
.
namespace
;
get_namespace
(
init_ns
);
our_ns
=
current
->
namespace
;
current
->
namespace
=
init_ns
;
put_namespace
(
our_ns
);
read_lock
(
&
init_fs
->
lock
);
rootmnt
=
mntget
(
init_fs
->
rootmnt
);
root
=
dget
(
init_fs
->
root
);
pwdmnt
=
mntget
(
init_fs
->
pwdmnt
);
pwd
=
dget
(
init_fs
->
pwd
);
read_unlock
(
&
init_fs
->
lock
);
/* FIXME - unsafe ->fs access */
our_fs
=
current
->
fs
;
our_fs
->
umask
=
init_fs
->
umask
;
set_fs_root
(
our_fs
,
rootmnt
,
root
);
set_fs_pwd
(
our_fs
,
pwdmnt
,
pwd
);
write_lock
(
&
our_fs
->
lock
);
if
(
our_fs
->
altroot
)
{
struct
vfsmount
*
mnt
=
our_fs
->
altrootmnt
;
struct
dentry
*
dentry
=
our_fs
->
altroot
;
our_fs
->
altrootmnt
=
NULL
;
our_fs
->
altroot
=
NULL
;
write_unlock
(
&
our_fs
->
lock
);
dput
(
dentry
);
mntput
(
mnt
);
}
else
write_unlock
(
&
our_fs
->
lock
);
dput
(
root
);
mntput
(
rootmnt
);
dput
(
pwd
);
mntput
(
pwdmnt
);
}
int
exec_usermodehelper
(
char
*
program_path
,
char
*
argv
[],
char
*
envp
[])
{
int
i
;
struct
task_struct
*
curtask
=
current
;
set_special_pids
(
1
,
1
);
use_init_fs_context
();
/* Prevent parent user process from sending signals to child.
Otherwise, if the modprobe program does not exist, it might
be possible to get a user defined signal handler to execute
as the super user right after the execve fails if you time
the signal just right.
*/
flush_signals
(
curtask
);
flush_signal_handlers
(
curtask
);
spin_lock_irq
(
&
curtask
->
sighand
->
siglock
);
sigemptyset
(
&
curtask
->
blocked
);
recalc_sigpending
();
spin_unlock_irq
(
&
curtask
->
sighand
->
siglock
);
for
(
i
=
0
;
i
<
curtask
->
files
->
max_fds
;
i
++
)
{
if
(
curtask
->
files
->
fd
[
i
])
close
(
i
);
}
switch_uid
(
INIT_USER
);
/* Give kmod all effective privileges.. */
curtask
->
euid
=
curtask
->
fsuid
=
0
;
curtask
->
egid
=
curtask
->
fsgid
=
0
;
security_task_kmod_set_label
();
/* Allow execve args to be in kernel space. */
set_fs
(
KERNEL_DS
);
/* Go, go, go... */
if
(
execve
(
program_path
,
argv
,
envp
)
<
0
)
return
-
errno
;
return
0
;
}
#ifdef CONFIG_KMOD
/*
...
...
@@ -144,29 +45,6 @@ int exec_usermodehelper(char *program_path, char *argv[], char *envp[])
*/
char
modprobe_path
[
256
]
=
"/sbin/modprobe"
;
static
int
exec_modprobe
(
void
*
module_name
)
{
static
char
*
envp
[]
=
{
"HOME=/"
,
"TERM=linux"
,
"PATH=/sbin:/usr/sbin:/bin:/usr/bin"
,
NULL
};
char
*
argv
[]
=
{
modprobe_path
,
"--"
,
(
char
*
)
module_name
,
NULL
};
int
ret
;
if
(
!
system_running
)
return
-
EBUSY
;
ret
=
exec_usermodehelper
(
modprobe_path
,
argv
,
envp
);
if
(
ret
)
{
static
unsigned
long
last
;
unsigned
long
now
=
jiffies
;
if
(
now
-
last
>
HZ
)
{
last
=
now
;
printk
(
KERN_DEBUG
"kmod: failed to exec %s -s -k %s, errno = %d
\n
"
,
modprobe_path
,
(
char
*
)
module_name
,
errno
);
}
}
return
ret
;
}
/**
* request_module - try to load a kernel module
* @module_name: Name of module
...
...
@@ -180,24 +58,18 @@ static int exec_modprobe(void * module_name)
* If module auto-loading support is disabled then this function
* becomes a no-operation.
*/
int
request_module
(
const
char
*
module_name
)
int
request_module
(
const
char
*
module_name
)
{
pid_t
pid
;
int
waitpid_result
;
sigset_t
tmpsig
;
int
i
,
ret
;
unsigned
int
max_modprobes
;
int
ret
;
char
*
argv
[]
=
{
modprobe_path
,
"--"
,
(
char
*
)
module_name
,
NULL
};
static
char
*
envp
[]
=
{
"HOME=/"
,
"TERM=linux"
,
"PATH=/sbin:/usr/sbin:/bin:/usr/bin"
,
NULL
};
static
atomic_t
kmod_concurrent
=
ATOMIC_INIT
(
0
);
#define MAX_KMOD_CONCURRENT 50
/* Completely arbitrary value - KAO */
static
int
kmod_loop_msg
;
unsigned
long
saved_policy
=
current
->
policy
;
current
->
policy
=
SCHED_NORMAL
;
/* Don't allow request_module() when the system isn't set up */
if
(
!
system_running
)
{
printk
(
KERN_ERR
"request_module[%s]: not ready
\n
"
,
module_name
);
ret
=
-
EPERM
;
goto
out
;
}
/* If modprobe needs a service that is in a module, we get a recursive
* loop. Limit the number of running kmod threads to max_threads/2 or
...
...
@@ -207,61 +79,44 @@ int request_module(const char * module_name)
* process tables to get the command line, proc_pid_cmdline is static
* and it is not worth changing the proc code just to handle this case.
* KAO.
*
* "trace the ppid" is simple, but will fail if someone's
* parent exits. I think this is as good as it gets. --RR
*/
i
=
max_threads
/
2
;
if
(
i
>
MAX_KMOD_CONCURRENT
)
i
=
MAX_KMOD_CONCURRENT
;
max_modprobes
=
min
(
max_threads
/
2
,
MAX_KMOD_CONCURRENT
);
atomic_inc
(
&
kmod_concurrent
);
if
(
atomic_read
(
&
kmod_concurrent
)
>
i
)
{
if
(
atomic_read
(
&
kmod_concurrent
)
>
max_modprobes
)
{
/* We may be blaming an innocent here, but unlikely */
if
(
kmod_loop_msg
++
<
5
)
printk
(
KERN_ERR
"kmod: runaway modprobe loop assumed and stopped
\n
"
);
"request_module: runaway loop modprobe %s
\n
"
,
module_name
);
atomic_dec
(
&
kmod_concurrent
);
ret
=
-
ENOMEM
;
goto
out
;
return
-
ENOMEM
;
}
pid
=
kernel_thread
(
exec_modprobe
,
(
void
*
)
module_name
,
0
);
if
(
pid
<
0
)
{
printk
(
KERN_ERR
"request_module[%s]: fork failed, errno %d
\n
"
,
module_name
,
-
pid
);
atomic_dec
(
&
kmod_concurrent
);
ret
=
pid
;
goto
out
;
ret
=
call_usermodehelper
(
modprobe_path
,
argv
,
envp
,
1
);
if
(
ret
!=
0
)
{
static
unsigned
long
last
;
unsigned
long
now
=
jiffies
;
if
(
now
-
last
>
HZ
)
{
last
=
now
;
printk
(
KERN_DEBUG
"request_module: failed %s -- %s. error = %d
\n
"
,
modprobe_path
,
module_name
,
ret
);
}
/* Block everything but SIGKILL/SIGSTOP */
spin_lock_irq
(
&
current
->
sighand
->
siglock
);
tmpsig
=
current
->
blocked
;
siginitsetinv
(
&
current
->
blocked
,
sigmask
(
SIGKILL
)
|
sigmask
(
SIGSTOP
));
recalc_sigpending
();
spin_unlock_irq
(
&
current
->
sighand
->
siglock
);
waitpid_result
=
waitpid
(
pid
,
NULL
,
__WCLONE
);
atomic_dec
(
&
kmod_concurrent
);
/* Allow signals again.. */
spin_lock_irq
(
&
current
->
sighand
->
siglock
);
current
->
blocked
=
tmpsig
;
recalc_sigpending
();
spin_unlock_irq
(
&
current
->
sighand
->
siglock
);
if
(
waitpid_result
!=
pid
)
{
printk
(
KERN_ERR
"request_module[%s]: waitpid(%d,...) failed, errno %d
\n
"
,
module_name
,
pid
,
-
waitpid_result
);
}
ret
=
0
;
out:
current
->
policy
=
saved_policy
;
atomic_dec
(
&
kmod_concurrent
);
return
ret
;
}
#endif
/* CONFIG_KMOD */
#ifdef CONFIG_HOTPLUG
/*
hotplug path is set via /proc/sys
invoked by hotplug-aware bus drivers,
with
exec_usermodehelper and some thread-spawn
er
with
call_usermodehelp
er
argv [0] = hotplug_path;
argv [1] = "usb", "scsi", "pci", "network", etc;
...
...
@@ -285,7 +140,8 @@ struct subprocess_info {
char
*
path
;
char
**
argv
;
char
**
envp
;
pid_t
retval
;
int
wait
;
int
retval
;
};
/*
...
...
@@ -298,13 +154,30 @@ static int ____call_usermodehelper(void *data)
retval
=
-
EPERM
;
if
(
current
->
fs
->
root
)
retval
=
exec
_usermodehelper
(
sub_info
->
path
,
sub_info
->
argv
,
sub_info
->
envp
);
retval
=
exec
ve
(
sub_info
->
path
,
sub_info
->
argv
,
sub_info
->
envp
);
/* Exec failed? */
sub_info
->
retval
=
(
pid_t
)
retval
;
sub_info
->
retval
=
retval
;
do_exit
(
0
);
}
/* Keventd can't block, but this (a child) can. */
static
int
wait_for_helper
(
void
*
data
)
{
struct
subprocess_info
*
sub_info
=
data
;
pid_t
pid
;
pid
=
kernel_thread
(
____call_usermodehelper
,
sub_info
,
CLONE_VFORK
|
SIGCHLD
);
if
(
pid
<
0
)
sub_info
->
retval
=
pid
;
else
sys_wait4
(
pid
,
(
unsigned
int
*
)
&
sub_info
->
retval
,
0
,
NULL
);
complete
(
sub_info
->
complete
);
return
0
;
}
/*
* This is run by keventd.
*/
...
...
@@ -313,14 +186,21 @@ static void __call_usermodehelper(void *data)
struct
subprocess_info
*
sub_info
=
data
;
pid_t
pid
;
/*
* CLONE_VFORK: wait until the usermode helper has execve'd successfully
* We need the data structures to stay around until that is done.
*/
pid
=
kernel_thread
(
____call_usermodehelper
,
sub_info
,
CLONE_VFORK
|
SIGCHLD
);
if
(
pid
<
0
)
/* CLONE_VFORK: wait until the usermode helper has execve'd
* successfully We need the data structures to stay around
* until that is done. */
if
(
sub_info
->
wait
)
pid
=
kernel_thread
(
wait_for_helper
,
sub_info
,
CLONE_KERNEL
|
SIGCHLD
);
else
pid
=
kernel_thread
(
____call_usermodehelper
,
sub_info
,
CLONE_VFORK
|
SIGCHLD
);
if
(
pid
<
0
)
{
sub_info
->
retval
=
pid
;
complete
(
sub_info
->
complete
);
}
else
if
(
!
sub_info
->
wait
)
complete
(
sub_info
->
complete
);
}
/**
...
...
@@ -328,15 +208,17 @@ static void __call_usermodehelper(void *data)
* @path: pathname for the application
* @argv: null-terminated argument list
* @envp: null-terminated environment list
* @wait: wait for the application to finish and return status.
*
* Runs a user-space application. The application is started
asynchronously. It
*
runs as a child of keventd. It runs with full root capabilities. keventd silently
*
reaps the child when it exits
.
* Runs a user-space application. The application is started
*
asynchronously if wait is not set, and runs as a child of keventd.
*
(ie. it runs with full root capabilities)
.
*
* Must be called from process context. Returns zero on success, else a negative
* error code.
* Must be called from process context. Returns a negative error code
* if program was not execed successfully, or (exitcode << 8 + signal)
* of the application (0 if wait is not set).
*/
int
call_usermodehelper
(
char
*
path
,
char
**
argv
,
char
**
envp
)
int
call_usermodehelper
(
char
*
path
,
char
**
argv
,
char
**
envp
,
int
wait
)
{
DECLARE_COMPLETION
(
done
);
struct
subprocess_info
sub_info
=
{
...
...
@@ -344,6 +226,7 @@ int call_usermodehelper(char *path, char **argv, char **envp)
.
path
=
path
,
.
argv
=
argv
,
.
envp
=
envp
,
.
wait
=
wait
,
.
retval
=
0
,
};
DECLARE_WORK
(
work
,
__call_usermodehelper
,
&
sub_info
);
...
...
@@ -381,7 +264,6 @@ void dev_probe_unlock(void)
up
(
&
dev_probe_sem
);
}
EXPORT_SYMBOL
(
exec_usermodehelper
);
EXPORT_SYMBOL
(
call_usermodehelper
);
#ifdef CONFIG_KMOD
...
...
net/bluetooth/hci_core.c
View file @
ac94a58a
...
...
@@ -114,7 +114,7 @@ static int hci_run_hotplug(char *dev, char *action)
envp
[
3
]
=
astr
;
envp
[
4
]
=
NULL
;
return
call_usermodehelper
(
argv
[
0
],
argv
,
envp
);
return
call_usermodehelper
(
argv
[
0
],
argv
,
envp
,
0
);
}
#else
#define hci_run_hotplug(A...)
...
...
net/core/dev.c
View file @
ac94a58a
...
...
@@ -2942,6 +2942,6 @@ static int net_run_sbin_hotplug(struct net_device *dev, char *action)
envp
[
i
++
]
=
action_str
;
envp
[
i
]
=
0
;
return
call_usermodehelper
(
argv
[
0
],
argv
,
envp
);
return
call_usermodehelper
(
argv
[
0
],
argv
,
envp
,
0
);
}
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment