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
Kirill Smelkov
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