diff options
author | Andrew Morton <akpm@linux-foundation.org> | 2012-07-30 17:40:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 20:25:13 -0400 |
commit | b57b44ae698944ffc6161352b8ff5c9cf9c592e2 (patch) | |
tree | 15d8d4c9681c2cba7c882f29b1b4f88378928095 /kernel/sys.c | |
parent | 45226e944ce071d0231949f2fea90969437cd2dc (diff) |
kernel/sys.c: avoid argv_free(NULL)
If argv_split() failed, the code will end up calling argv_free(NULL). Fix
it up and clean things up a bit.
Addresses Coverity report 703573.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Serge Hallyn <serge.hallyn@canonical.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: WANG Cong <xiyou.wangcong@gmail.com>
Cc: Alan Cox <alan@linux.intel.com>
Cc: David Rientjes <rientjes@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index b04ae0390df3..241507f23eca 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -2186,46 +2186,52 @@ static void argv_cleanup(struct subprocess_info *info) | |||
2186 | argv_free(info->argv); | 2186 | argv_free(info->argv); |
2187 | } | 2187 | } |
2188 | 2188 | ||
2189 | /** | 2189 | static int __orderly_poweroff(void) |
2190 | * orderly_poweroff - Trigger an orderly system poweroff | ||
2191 | * @force: force poweroff if command execution fails | ||
2192 | * | ||
2193 | * This may be called from any context to trigger a system shutdown. | ||
2194 | * If the orderly shutdown fails, it will force an immediate shutdown. | ||
2195 | */ | ||
2196 | int orderly_poweroff(bool force) | ||
2197 | { | 2190 | { |
2198 | int argc; | 2191 | int argc; |
2199 | char **argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); | 2192 | char **argv; |
2200 | static char *envp[] = { | 2193 | static char *envp[] = { |
2201 | "HOME=/", | 2194 | "HOME=/", |
2202 | "PATH=/sbin:/bin:/usr/sbin:/usr/bin", | 2195 | "PATH=/sbin:/bin:/usr/sbin:/usr/bin", |
2203 | NULL | 2196 | NULL |
2204 | }; | 2197 | }; |
2205 | int ret = -ENOMEM; | 2198 | int ret; |
2206 | 2199 | ||
2200 | argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); | ||
2207 | if (argv == NULL) { | 2201 | if (argv == NULL) { |
2208 | printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", | 2202 | printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", |
2209 | __func__, poweroff_cmd); | 2203 | __func__, poweroff_cmd); |
2210 | goto out; | 2204 | return -ENOMEM; |
2211 | } | 2205 | } |
2212 | 2206 | ||
2213 | ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_NO_WAIT, | 2207 | ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_NO_WAIT, |
2214 | NULL, argv_cleanup, NULL); | 2208 | NULL, argv_cleanup, NULL); |
2215 | out: | ||
2216 | if (likely(!ret)) | ||
2217 | return 0; | ||
2218 | |||
2219 | if (ret == -ENOMEM) | 2209 | if (ret == -ENOMEM) |
2220 | argv_free(argv); | 2210 | argv_free(argv); |
2221 | 2211 | ||
2222 | if (force) { | 2212 | return ret; |
2213 | } | ||
2214 | |||
2215 | /** | ||
2216 | * orderly_poweroff - Trigger an orderly system poweroff | ||
2217 | * @force: force poweroff if command execution fails | ||
2218 | * | ||
2219 | * This may be called from any context to trigger a system shutdown. | ||
2220 | * If the orderly shutdown fails, it will force an immediate shutdown. | ||
2221 | */ | ||
2222 | int orderly_poweroff(bool force) | ||
2223 | { | ||
2224 | int ret = __orderly_poweroff(); | ||
2225 | |||
2226 | if (ret && force) { | ||
2223 | printk(KERN_WARNING "Failed to start orderly shutdown: " | 2227 | printk(KERN_WARNING "Failed to start orderly shutdown: " |
2224 | "forcing the issue\n"); | 2228 | "forcing the issue\n"); |
2225 | 2229 | ||
2226 | /* I guess this should try to kick off some daemon to | 2230 | /* |
2227 | sync and poweroff asap. Or not even bother syncing | 2231 | * I guess this should try to kick off some daemon to sync and |
2228 | if we're doing an emergency shutdown? */ | 2232 | * poweroff asap. Or not even bother syncing if we're doing an |
2233 | * emergency shutdown? | ||
2234 | */ | ||
2229 | emergency_sync(); | 2235 | emergency_sync(); |
2230 | kernel_power_off(); | 2236 | kernel_power_off(); |
2231 | } | 2237 | } |