summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/chrome_browser_main_chromeos.cc56
-rw-r--r--chrome/browser/chromeos/chrome_browser_main_chromeos.h4
-rw-r--r--chrome/browser/low_memory_observer.cc10
-rw-r--r--chrome/browser/low_memory_observer.h5
-rw-r--r--chrome/browser/oom_priority_manager.cc45
-rw-r--r--chrome/browser/ui/views/sad_tab_view.cc43
-rw-r--r--content/browser/zygote_host_impl_linux.cc42
-rw-r--r--content/browser/zygote_host_impl_linux.h3
-rw-r--r--content/public/browser/zygote_host_linux.h6
-rw-r--r--sandbox/linux/suid/process_util.h9
-rw-r--r--sandbox/linux/suid/process_util_linux.c35
-rw-r--r--sandbox/linux/suid/sandbox.c28
-rw-r--r--sandbox/linux/suid/sandbox.h24
-rw-r--r--sandbox/linux/suid/suid_unsafe_environment_variables.h8
-rw-r--r--sandbox/sandbox.gyp1
15 files changed, 275 insertions, 44 deletions
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index ea86e8f..5563502 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -49,6 +49,7 @@
#include "chrome/browser/chromeos/web_socket_proxy_controller.h"
#include "chrome/browser/chromeos/xinput_hierarchy_changed_event_listener.h"
#include "chrome/browser/defaults.h"
+#include "chrome/browser/low_memory_observer.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/oom_priority_manager.h"
#include "chrome/browser/policy/browser_policy_connector.h"
@@ -59,6 +60,7 @@
#include "chrome/browser/ui/views/browser_dialogs.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/chrome_version_info.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/pref_names.h"
#include "chromeos/dbus/dbus_thread_manager.h"
@@ -285,6 +287,13 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopStart() {
ChromeBrowserMainPartsLinux::PostMainMessageLoopStart();
}
+int ChromeBrowserMainPartsChromeos::PreCreateThreads() {
+ // Set up field trial for low memory headroom settings.
+ SetupLowMemoryHeadroomFieldTrial();
+
+ return ChromeBrowserMainPartsLinux::PreCreateThreads();
+}
+
// Threads are initialized MainMessageLoopStart and MainMessageLoopRun.
void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() {
@@ -495,3 +504,50 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
ChromeBrowserMainPartsLinux::PostMainMessageLoopRun();
}
+
+void ChromeBrowserMainPartsChromeos::SetupLowMemoryHeadroomFieldTrial() {
+ chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
+ // Only enable this experiment on Canary and Dev, since it's possible
+ // that this will make the machine unstable.
+ // Note that to have this code execute in a developer build,
+ // then chrome::VersionInfo::CHANNEL_UNKNOWN needs to be added here.
+ if (channel == chrome::VersionInfo::CHANNEL_CANARY ||
+ channel == chrome::VersionInfo::CHANNEL_DEV) {
+ const base::FieldTrial::Probability kDivisor = 7;
+ // 1 in 7 probability of being in each group. If the default value for the
+ // kernel matches one of the experiment groups, then they will have
+ // identical results.
+ const base::FieldTrial::Probability kEnableProbability = 1;
+ scoped_refptr<base::FieldTrial> trial =
+ base::FieldTrialList::FactoryGetFieldTrial(
+ "LowMemoryMargin", kDivisor, "default", 2012, 6, 30, NULL);
+ int disable = trial->AppendGroup("off", kEnableProbability);
+ int margin_0mb = trial->AppendGroup("0mb", kEnableProbability);
+ int margin_25mb = trial->AppendGroup("25mb", kEnableProbability);
+ int margin_50mb = trial->AppendGroup("50mb", kEnableProbability);
+ int margin_100mb = trial->AppendGroup("100mb", kEnableProbability);
+ int margin_200mb = trial->AppendGroup("200mb", kEnableProbability);
+ if (trial->group() == disable) {
+ LOG(WARNING) << "low_mem: Part of 'off' experiment";
+ browser::LowMemoryObserver::SetLowMemoryMargin(0);
+ } else if (trial->group() == margin_0mb) {
+ LOG(WARNING) << "low_mem: Part of '0MB' experiment";
+ browser::LowMemoryObserver::SetLowMemoryMargin(50);
+ } else if (trial->group() == margin_25mb) {
+ LOG(WARNING) << "low_mem: Part of '25MB' experiment";
+ browser::LowMemoryObserver::SetLowMemoryMargin(50);
+ } else if (trial->group() == margin_50mb) {
+ LOG(WARNING) << "low_mem: Part of '50MB' experiment";
+ browser::LowMemoryObserver::SetLowMemoryMargin(50);
+ } else if (trial->group() == margin_100mb) {
+ LOG(WARNING) << "low_mem: Part of '100MB' experiment";
+ browser::LowMemoryObserver::SetLowMemoryMargin(100);
+ } else if (trial->group() == margin_200mb) {
+ LOG(WARNING) << "low_mem: Part of '200MB' experiment";
+ browser::LowMemoryObserver::SetLowMemoryMargin(200);
+ } else {
+ LOG(WARNING) << "low_mem: Part of 'default' experiment";
+ }
+ }
+}
+
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
index a001ea1..4cc2a61 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -30,6 +30,7 @@ class ChromeBrowserMainPartsChromeos : public ChromeBrowserMainPartsLinux {
virtual void PreEarlyInitialization() OVERRIDE;
virtual void PreMainMessageLoopStart() OVERRIDE;
virtual void PostMainMessageLoopStart() OVERRIDE;
+ virtual int PreCreateThreads() OVERRIDE;
virtual void PreMainMessageLoopRun() OVERRIDE;
// Stages called from PreMainMessageLoopRun.
@@ -40,6 +41,9 @@ class ChromeBrowserMainPartsChromeos : public ChromeBrowserMainPartsLinux {
virtual void PostMainMessageLoopRun() OVERRIDE;
+ // Set up field trial for low memory headroom settings.
+ void SetupLowMemoryHeadroomFieldTrial();
+
private:
scoped_ptr<chromeos::BrightnessObserver> brightness_observer_;
scoped_ptr<chromeos::ResumeObserver> resume_observer_;
diff --git a/chrome/browser/low_memory_observer.cc b/chrome/browser/low_memory_observer.cc
index 8788f03..5396696 100644
--- a/chrome/browser/low_memory_observer.cc
+++ b/chrome/browser/low_memory_observer.cc
@@ -15,6 +15,11 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/oom_priority_manager.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/zygote_host_linux.h"
+
+#if !defined(OS_CHROMEOS)
+#error This file only meant to be compiled on ChromeOS
+#endif
using content::BrowserThread;
@@ -180,4 +185,9 @@ void LowMemoryObserver::Stop() {
observer_.get()));
}
+// static
+void LowMemoryObserver::SetLowMemoryMargin(int64 margin_mb) {
+ content::ZygoteHost::GetInstance()->AdjustLowMemoryMargin(margin_mb);
+}
+
} // namespace browser
diff --git a/chrome/browser/low_memory_observer.h b/chrome/browser/low_memory_observer.h
index 088a74c..1caad25 100644
--- a/chrome/browser/low_memory_observer.h
+++ b/chrome/browser/low_memory_observer.h
@@ -34,6 +34,11 @@ class LowMemoryObserver {
void Start();
void Stop();
+
+ // Sets the threshold level of the low memory notifier in megabytes. Setting
+ // to -1 will turn off the low memory notifier.
+ static void SetLowMemoryMargin(int64 margin_mb);
+
private:
scoped_refptr<LowMemoryObserverImpl> observer_;
diff --git a/chrome/browser/oom_priority_manager.cc b/chrome/browser/oom_priority_manager.cc
index 0d87d4c..60fa186 100644
--- a/chrome/browser/oom_priority_manager.cc
+++ b/chrome/browser/oom_priority_manager.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/process.h"
#include "base/process_util.h"
@@ -51,14 +52,25 @@ namespace browser {
namespace {
+// Name of the experiment to run.
+const char kExperiment[] = "LowMemoryMargin";
+
+#define EXPERIMENT_CUSTOM_COUNTS(name, sample, min, max, buckets) \
+ UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, buckets); \
+ if (base::FieldTrialList::TrialExists(kExperiment)) \
+ UMA_HISTOGRAM_CUSTOM_COUNTS( \
+ base::FieldTrial::MakeName(name, kExperiment), \
+ sample, min, max, buckets);
+
// Record a time in seconds, over a potential interval of about a day. Must be a
// macro and not a function because the histograms system requires a unique
// static variable at the site of each call.
-#define UMA_HISTOGRAM_SECONDS(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
- name, sample, 1, 10000, 50)
+#define EXPERIMENT_HISTOGRAM_SECONDS(name, sample) \
+ EXPERIMENT_CUSTOM_COUNTS(name, sample, 1, 10000, 50)
+
// Record a size in megabytes, over a potential interval up to 32 GB.
-#define UMA_HISTOGRAM_MEGABYTES(name, sample) UMA_HISTOGRAM_CUSTOM_COUNTS( \
- name, sample, 1, 32768, 50)
+#define EXPERIMENT_HISTOGRAM_MEGABYTES(name, sample) \
+ EXPERIMENT_CUSTOM_COUNTS(name, sample, 1, 32768, 50)
// The default interval in seconds after which to adjust the oom_score_adj
// value.
@@ -241,11 +253,11 @@ bool OomPriorityManager::DiscardTabById(int64 target_web_contents_id) {
void OomPriorityManager::RecordDiscardStatistics() {
// Record a raw count so we can compare to discard reloads.
discard_count_++;
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Tabs.Discard.DiscardCount", discard_count_, 1, 1000, 50);
+ EXPERIMENT_CUSTOM_COUNTS("Tabs.Discard.DiscardCount",
+ discard_count_, 1, 1000, 50);
// TODO(jamescook): Maybe incorporate extension count?
- UMA_HISTOGRAM_COUNTS_100("Tabs.Discard.TabCount", GetTabCount());
+ EXPERIMENT_CUSTOM_COUNTS("Tabs.Discard.TabCount", GetTabCount(), 1, 100, 50);
// TODO(jamescook): If the time stats prove too noisy, then divide up users
// based on how heavily they use Chrome using tab count as a proxy.
@@ -254,23 +266,24 @@ void OomPriorityManager::RecordDiscardStatistics() {
// This is the first discard this session.
TimeDelta interval = TimeTicks::Now() - start_time_;
int interval_seconds = static_cast<int>(interval.InSeconds());
- UMA_HISTOGRAM_SECONDS("Tabs.Discard.InitialTime", interval_seconds);
+ EXPERIMENT_HISTOGRAM_SECONDS("Tabs.Discard.InitialTime", interval_seconds);
} else {
// Not the first discard, so compute time since last discard.
TimeDelta interval = TimeTicks::Now() - last_discard_time_;
int interval_seconds = static_cast<int>(interval.InSeconds());
- UMA_HISTOGRAM_SECONDS("Tabs.Discard.IntervalTime", interval_seconds);
+ EXPERIMENT_HISTOGRAM_SECONDS("Tabs.Discard.IntervalTime", interval_seconds);
}
// Record Chrome's concept of system memory usage at the time of the discard.
base::SystemMemoryInfoKB memory;
if (base::GetSystemMemoryInfo(&memory)) {
- int mem_anonymous_kb = memory.active_anon + memory.inactive_anon;
- UMA_HISTOGRAM_MEGABYTES("Tabs.Discard.MemAnonymousMB",
- mem_anonymous_kb / 1024);
- int mem_available_kb =
- memory.active_file + memory.inactive_file + memory.free;
- UMA_HISTOGRAM_MEGABYTES("Tabs.Discard.MemAvailableMB",
- mem_available_kb / 1024);
+ int mem_anonymous_mb = (memory.active_anon + memory.inactive_anon) / 1024;
+ EXPERIMENT_HISTOGRAM_MEGABYTES("Tabs.Discard.MemAnonymousMB",
+ mem_anonymous_mb);
+
+ int mem_available_mb =
+ (memory.active_file + memory.inactive_file + memory.free) / 1024;
+ EXPERIMENT_HISTOGRAM_MEGABYTES("Tabs.Discard.MemAvailableMB",
+ mem_available_mb);
}
// Set up to record the next interval.
last_discard_time_ = TimeTicks::Now();
diff --git a/chrome/browser/ui/views/sad_tab_view.cc b/chrome/browser/ui/views/sad_tab_view.cc
index d64b2ac..566cf9b 100644
--- a/chrome/browser/ui/views/sad_tab_view.cc
+++ b/chrome/browser/ui/views/sad_tab_view.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/feedback/feedback_util.h"
@@ -28,23 +29,37 @@
using content::OpenURLParams;
using content::WebContents;
-static const int kPadding = 20;
-static const float kMessageSize = 0.65f;
-static const SkColor kTextColor = SK_ColorWHITE;
-static const SkColor kCrashColor = SkColorSetRGB(35, 48, 64);
-static const SkColor kKillColor = SkColorSetRGB(57, 48, 88);
+namespace {
+
+const int kPadding = 20;
+const float kMessageSize = 0.65f;
+const SkColor kTextColor = SK_ColorWHITE;
+const SkColor kCrashColor = SkColorSetRGB(35, 48, 64);
+const SkColor kKillColor = SkColorSetRGB(57, 48, 88);
const char kCategoryTagCrash[] = "Crash";
// Font size correction.
#if defined(CROS_FONTS_USING_BCI)
-static const int kTitleFontSizeDelta = 1;
-static const int kMessageFontSizeDelta = 0;
+const int kTitleFontSizeDelta = 1;
+const int kMessageFontSizeDelta = 0;
#else
-static const int kTitleFontSizeDelta = 2;
-static const int kMessageFontSizeDelta = 1;
+const int kTitleFontSizeDelta = 2;
+const int kMessageFontSizeDelta = 1;
#endif
+// Name of the experiment to run.
+const char kExperiment[] = "LowMemoryMargin";
+
+#define EXPERIMENT_CUSTOM_COUNTS(name, sample, min, max, buckets) \
+ UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, buckets); \
+ if (base::FieldTrialList::TrialExists(kExperiment)) \
+ UMA_HISTOGRAM_CUSTOM_COUNTS( \
+ base::FieldTrial::MakeName(name, kExperiment), \
+ sample, min, max, buckets);
+
+} // namespace
+
SadTabView::SadTabView(WebContents* web_contents, Kind kind)
: web_contents_(web_contents),
kind_(kind),
@@ -70,14 +85,16 @@ SadTabView::SadTabView(WebContents* web_contents, Kind kind)
switch (kind_) {
case CRASHED: {
static int crashed = 0;
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Tabs.SadTab.CrashCreated", ++crashed, 1, 1000, 50);
+ crashed++;
+ EXPERIMENT_CUSTOM_COUNTS(
+ "Tabs.SadTab.CrashCreated", crashed, 1, 1000, 50);
break;
}
case KILLED: {
static int killed = 0;
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Tabs.SadTab.KillCreated", ++killed, 1, 1000, 50);
+ killed++;
+ EXPERIMENT_CUSTOM_COUNTS(
+ "Tabs.SadTab.KillCreated", killed, 1, 1000, 50);
break;
}
default:
diff --git a/content/browser/zygote_host_impl_linux.cc b/content/browser/zygote_host_impl_linux.cc
index 519fa12..40dcc6a 100644
--- a/content/browser/zygote_host_impl_linux.cc
+++ b/content/browser/zygote_host_impl_linux.cc
@@ -30,6 +30,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
+#include "sandbox/linux/suid/sandbox.h"
#include "sandbox/linux/suid/suid_unsafe_environment_variables.h"
#if defined(USE_TCMALLOC)
@@ -371,13 +372,9 @@ void ZygoteHostImpl::AdjustRendererOOMScore(base::ProcessHandle pid,
if (IsHeapProfilerRunning())
return;
#endif
- // The command line switch used for supplying the OOM adjustment score
- // to the setuid sandbox.
- static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score";
-
std::vector<std::string> adj_oom_score_cmdline;
adj_oom_score_cmdline.push_back(sandbox_binary_);
- adj_oom_score_cmdline.push_back(kAdjustOOMScoreSwitch);
+ adj_oom_score_cmdline.push_back(sandbox::kAdjustOOMScoreSwitch);
adj_oom_score_cmdline.push_back(base::Int64ToString(pid));
adj_oom_score_cmdline.push_back(base::IntToString(score));
@@ -393,6 +390,41 @@ void ZygoteHostImpl::AdjustRendererOOMScore(base::ProcessHandle pid,
}
#endif
+void ZygoteHostImpl::AdjustLowMemoryMargin(int64 margin_mb) {
+#if defined(OS_CHROMEOS)
+ // You can't change the low memory margin unless you're root. Because of this,
+ // we can't set the low memory margin from the browser process.
+ // So, we use the SUID binary to change it for us.
+ if (using_suid_sandbox_) {
+#if defined(USE_TCMALLOC)
+ // If heap profiling is running, these processes are not exiting, at least
+ // on ChromeOS. The easiest thing to do is not launch them when profiling.
+ // TODO(stevenjb): Investigate further and fix.
+ if (IsHeapProfilerRunning())
+ return;
+#endif
+ std::vector<std::string> adj_low_mem_commandline;
+ adj_low_mem_commandline.push_back(sandbox_binary_);
+ adj_low_mem_commandline.push_back(sandbox::kAdjustLowMemMarginSwitch);
+ adj_low_mem_commandline.push_back(base::Int64ToString(margin_mb));
+
+ base::ProcessHandle sandbox_helper_process;
+ if (base::LaunchProcess(adj_low_mem_commandline, base::LaunchOptions(),
+ &sandbox_helper_process)) {
+ base::EnsureProcessGetsReaped(sandbox_helper_process);
+ } else {
+ LOG(ERROR) << "Unable to run suid sandbox to set low memory margin.";
+ }
+ }
+ // Don't adjust memory margin if we're not running with the sandbox: this
+ // isn't very common, and not doing it has little impact.
+#else
+ // Low memory notification is currently only implemented on ChromeOS.
+ NOTREACHED() << "AdjustLowMemoryMargin not implemented";
+#endif // defined(OS_CHROMEOS)
+}
+
+
void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) {
DCHECK(init_);
Pickle pickle;
diff --git a/content/browser/zygote_host_impl_linux.h b/content/browser/zygote_host_impl_linux.h
index 3c6e824..ad8dfac 100644
--- a/content/browser/zygote_host_impl_linux.h
+++ b/content/browser/zygote_host_impl_linux.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -55,6 +55,7 @@ class CONTENT_EXPORT ZygoteHostImpl : public content::ZygoteHost {
virtual int GetSandboxStatus() const OVERRIDE;
virtual void AdjustRendererOOMScore(base::ProcessHandle process_handle,
int score) OVERRIDE;
+ virtual void AdjustLowMemoryMargin(int64 margin_mb) OVERRIDE;
private:
friend struct DefaultSingletonTraits<ZygoteHostImpl>;
diff --git a/content/public/browser/zygote_host_linux.h b/content/public/browser/zygote_host_linux.h
index 2b79b30..cd9932e 100644
--- a/content/public/browser/zygote_host_linux.h
+++ b/content/public/browser/zygote_host_linux.h
@@ -46,6 +46,12 @@ class ZygoteHost {
// likely to be killed by the OOM killer.
virtual void AdjustRendererOOMScore(base::ProcessHandle process_handle,
int score) = 0;
+
+ // Adjust the point at which the low memory notifier in the kernel tells
+ // us that we're low on memory. When there is less than |margin_mb| left,
+ // then the notifier will notify us. Set |margin_mb| to -1 to turn off
+ // low memory notification altogether.
+ virtual void AdjustLowMemoryMargin(int64 margin_mb) = 0;
};
} // namespace content
diff --git a/sandbox/linux/suid/process_util.h b/sandbox/linux/suid/process_util.h
index 1826555..61f7b25 100644
--- a/sandbox/linux/suid/process_util.h
+++ b/sandbox/linux/suid/process_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -7,6 +7,7 @@
#ifndef SANDBOX_LINUX_SUID_PROCESS_UTIL_H_
#define SANDBOX_LINUX_SUID_PROCESS_UTIL_H_
+#pragma once
#include <stdbool.h>
#include <sys/types.h>
@@ -23,4 +24,10 @@
// values, of course.
BASE_EXPORT bool AdjustOOMScore(pid_t process, int score);
+// This adjusts /sys/kernel/mm/chromeos-low_mem/margin so that
+// the kernel notifies us that we are low on memory when less than
+// |margin_mb| megabytes are available. Setting |margin_mb| to -1
+// turns off low memory notification.
+BASE_EXPORT bool AdjustLowMemoryMargin(int64_t margin_mb);
+
#endif // SANDBOX_LINUX_SUID_PROCESS_UTIL_H_
diff --git a/sandbox/linux/suid/process_util_linux.c b/sandbox/linux/suid/process_util_linux.c
index 13f45ce..1829558 100644
--- a/sandbox/linux/suid/process_util_linux.c
+++ b/sandbox/linux/suid/process_util_linux.c
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -24,6 +24,12 @@
static const int kMaxOomScore = 1000;
static const int kMaxOldOomScore = 15;
+// Kernel pseudo-file that allows setting of the low memory margin.
+static const char kLowMemMarginFile[] =
+ "/sys/kernel/mm/chromeos-low_mem/margin";
+
+// NOTE: This is not the only version of this function in the source:
+// the base library (in process_util_linux.cc) also has its own C++ version.
bool AdjustOOMScore(pid_t process, int score) {
if (score < 0 || score > kMaxOomScore)
return false;
@@ -71,3 +77,30 @@ bool AdjustOOMScore(pid_t process, int score) {
close(fd);
return (bytes_written == len);
}
+
+bool AdjustLowMemoryMargin(int64_t margin_mb) {
+ int file_descriptor = open(kLowMemMarginFile, O_WRONLY);
+ if (file_descriptor < 0)
+ return false;
+
+ // Only allow those values which are reasonable, to prevent mischief.
+ char value[21];
+ switch (margin_mb) {
+ case -1L:
+ snprintf(value, sizeof(value), "off");
+ break;
+ case 0L:
+ case 25L:
+ case 50L:
+ case 100L:
+ case 200L:
+ snprintf(value, sizeof(value), "%zu", margin_mb);
+ break;
+ default:
+ return false;
+ }
+
+ bool success = (write(file_descriptor, value, strlen(value)) >= 0);
+ close(file_descriptor);
+ return success;
+}
diff --git a/sandbox/linux/suid/sandbox.c b/sandbox/linux/suid/sandbox.c
index a83291e..41a68c7 100644
--- a/sandbox/linux/suid/sandbox.c
+++ b/sandbox/linux/suid/sandbox.c
@@ -4,6 +4,8 @@
// http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
+#include "sandbox.h"
+
#define _GNU_SOURCE
#include <asm/unistd.h>
#include <errno.h>
@@ -38,7 +40,6 @@
#define CLONE_NEWNET 0x40000000
#endif
-static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score";
static const char kSandboxDescriptorEnvironmentVarName[] = "SBX_D";
static const char kSandboxHelperPidEnvironmentVarName[] = "SBX_HELPER_PID";
@@ -405,9 +406,10 @@ int main(int argc, char **argv) {
// when you call it with --find-inode INODE_NUMBER.
if (argc == 3 && (0 == strcmp(argv[1], kFindInodeSwitch))) {
pid_t pid;
- char* endptr;
+ char* endptr = NULL;
+ errno = 0;
ino_t inode = strtoull(argv[2], &endptr, 10);
- if (inode == ULLONG_MAX || *endptr)
+ if (inode == ULLONG_MAX || !endptr || *endptr || errno != 0)
return 1;
if (!FindProcessHoldingSocket(&pid, inode))
return 1;
@@ -417,17 +419,31 @@ int main(int argc, char **argv) {
// Likewise, we cannot adjust /proc/pid/oom_adj for sandboxed renderers
// because those files are owned by root. So we need another helper here.
if (argc == 4 && (0 == strcmp(argv[1], kAdjustOOMScoreSwitch))) {
- char* endptr;
+ char* endptr = NULL;
long score;
+ errno = 0;
unsigned long pid_ul = strtoul(argv[2], &endptr, 10);
- if (pid_ul == ULONG_MAX || *endptr)
+ if (pid_ul == ULONG_MAX || !endptr || *endptr || errno != 0)
return 1;
pid_t pid = pid_ul;
+ endptr = NULL;
+ errno = 0;
score = strtol(argv[3], &endptr, 10);
- if (score == LONG_MAX || score == LONG_MIN || *endptr)
+ if (score == LONG_MAX || score == LONG_MIN ||
+ !endptr || *endptr || errno != 0)
return 1;
return AdjustOOMScore(pid, score);
}
+#if defined(OS_CHROMEOS)
+ if (argc == 3 && (0 == strcmp(argv[1], kAdjustLowMemMarginSwitch))) {
+ char* endptr = NULL;
+ errno = 0;
+ unsigned long margin_mb = strtoul(argv[2], &endptr, 10);
+ if (!endptr || *endptr || errno != 0)
+ return 1;
+ return AdjustLowMemoryMargin(margin_mb);
+ }
+#endif
if (!MoveToNewNamespaces())
return 1;
diff --git a/sandbox/linux/suid/sandbox.h b/sandbox/linux/suid/sandbox.h
new file mode 100644
index 0000000..e9ae90c
--- /dev/null
+++ b/sandbox/linux/suid/sandbox.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SUID_SANDBOX_H_
+#define SANDBOX_LINUX_SUID_SANDBOX_H_
+#pragma once
+
+#if defined(__cplusplus)
+namespace sandbox {
+#endif
+
+// These are command line switches that may be used by other programs
+// (e.g. Chrome) to construct a command line for the sandbox.
+static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score";
+#if defined(OS_CHROMEOS)
+static const char kAdjustLowMemMarginSwitch[] = "--adjust-low-mem";
+#endif
+
+#if defined(__cplusplus)
+} // namespace sandbox
+#endif
+
+#endif // SANDBOX_LINUX_SUID_SANDBOX_H_
diff --git a/sandbox/linux/suid/suid_unsafe_environment_variables.h b/sandbox/linux/suid/suid_unsafe_environment_variables.h
index 5862010..d216819 100644
--- a/sandbox/linux/suid/suid_unsafe_environment_variables.h
+++ b/sandbox/linux/suid/suid_unsafe_environment_variables.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -13,6 +13,10 @@
// sysdeps/unix/sysv/linux/i386/dl-librecon.h
// sysdeps/generic/unsecvars.h
+#ifndef SANDBOX_LINUX_SUID_SUID_UNSAFE_ENVIRONMENT_VARIABLES_H_
+#define SANDBOX_LINUX_SUID_SUID_UNSAFE_ENVIRONMENT_VARIABLES_H_
+#pragma once
+
static const char* kSUIDUnsafeEnvironmentVariables[] = {
"LD_AOUT_LIBRARY_PATH",
"LD_AOUT_PRELOAD",
@@ -57,3 +61,5 @@ static inline char* SandboxSavedEnvironmentVariable(const char* envvar) {
return saved_envvar;
}
+
+#endif // SANDBOX_LINUX_SUID_SUID_UNSAFE_ENVIRONMENT_VARIABLES_H_
diff --git a/sandbox/sandbox.gyp b/sandbox/sandbox.gyp
index 50a9bfe..a3593c6 100644
--- a/sandbox/sandbox.gyp
+++ b/sandbox/sandbox.gyp
@@ -167,6 +167,7 @@
'linux/suid/linux_util.h',
'linux/suid/process_util.h',
'linux/suid/process_util_linux.c',
+ 'linux/suid/sandbox.h',
'linux/suid/sandbox.c',
],
'cflags': [