security/sandbox/win/src/job.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/sandbox/win/src/job.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,116 @@
     1.4 +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +#include "sandbox/win/src/job.h"
     1.9 +
    1.10 +#include "base/win/windows_version.h"
    1.11 +#include "sandbox/win/src/restricted_token.h"
    1.12 +
    1.13 +namespace sandbox {
    1.14 +
    1.15 +Job::~Job() {
    1.16 +  if (job_handle_)
    1.17 +    ::CloseHandle(job_handle_);
    1.18 +};
    1.19 +
    1.20 +DWORD Job::Init(JobLevel security_level, wchar_t *job_name,
    1.21 +                DWORD ui_exceptions) {
    1.22 +  if (job_handle_)
    1.23 +    return ERROR_ALREADY_INITIALIZED;
    1.24 +
    1.25 +  job_handle_ = ::CreateJobObject(NULL,   // No security attribute
    1.26 +                                  job_name);
    1.27 +  if (!job_handle_)
    1.28 +    return ::GetLastError();
    1.29 +
    1.30 +  JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
    1.31 +  JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0};
    1.32 +
    1.33 +  // Set the settings for the different security levels. Note: The higher levels
    1.34 +  // inherit from the lower levels.
    1.35 +  switch (security_level) {
    1.36 +    case JOB_LOCKDOWN: {
    1.37 +      jeli.BasicLimitInformation.LimitFlags |=
    1.38 +          JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
    1.39 +    }
    1.40 +    case JOB_RESTRICTED: {
    1.41 +      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
    1.42 +      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_READCLIPBOARD;
    1.43 +      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
    1.44 +      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_GLOBALATOMS;
    1.45 +    }
    1.46 +    case JOB_LIMITED_USER: {
    1.47 +      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS;
    1.48 +      jeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
    1.49 +      jeli.BasicLimitInformation.ActiveProcessLimit = 1;
    1.50 +    }
    1.51 +    case JOB_INTERACTIVE: {
    1.52 +      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
    1.53 +      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DESKTOP;
    1.54 +      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
    1.55 +    }
    1.56 +    case JOB_UNPROTECTED: {
    1.57 +      // The JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag is not supported on
    1.58 +      // Windows 2000. We need a mechanism on Windows 2000 to ensure
    1.59 +      // that processes in the job are terminated when the job is closed
    1.60 +      if (base::win::GetVersion() == base::win::VERSION_PRE_XP)
    1.61 +        break;
    1.62 +
    1.63 +      jeli.BasicLimitInformation.LimitFlags |=
    1.64 +          JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
    1.65 +      break;
    1.66 +    }
    1.67 +    default: {
    1.68 +      return ERROR_BAD_ARGUMENTS;
    1.69 +    }
    1.70 +  }
    1.71 +
    1.72 +  if (FALSE == ::SetInformationJobObject(job_handle_,
    1.73 +                                         JobObjectExtendedLimitInformation,
    1.74 +                                         &jeli,
    1.75 +                                         sizeof(jeli))) {
    1.76 +    return ::GetLastError();
    1.77 +  }
    1.78 +
    1.79 +  jbur.UIRestrictionsClass = jbur.UIRestrictionsClass & (~ui_exceptions);
    1.80 +  if (FALSE == ::SetInformationJobObject(job_handle_,
    1.81 +                                         JobObjectBasicUIRestrictions,
    1.82 +                                         &jbur,
    1.83 +                                         sizeof(jbur))) {
    1.84 +    return ::GetLastError();
    1.85 +  }
    1.86 +
    1.87 +  return ERROR_SUCCESS;
    1.88 +}
    1.89 +
    1.90 +DWORD Job::UserHandleGrantAccess(HANDLE handle) {
    1.91 +  if (!job_handle_)
    1.92 +    return ERROR_NO_DATA;
    1.93 +
    1.94 +  if (!::UserHandleGrantAccess(handle,
    1.95 +                               job_handle_,
    1.96 +                               TRUE)) {  // Access allowed.
    1.97 +    return ::GetLastError();
    1.98 +  }
    1.99 +
   1.100 +  return ERROR_SUCCESS;
   1.101 +}
   1.102 +
   1.103 +HANDLE Job::Detach() {
   1.104 +  HANDLE handle_temp = job_handle_;
   1.105 +  job_handle_ = NULL;
   1.106 +  return handle_temp;
   1.107 +}
   1.108 +
   1.109 +DWORD Job::AssignProcessToJob(HANDLE process_handle) {
   1.110 +  if (!job_handle_)
   1.111 +    return ERROR_NO_DATA;
   1.112 +
   1.113 +  if (FALSE == ::AssignProcessToJobObject(job_handle_, process_handle))
   1.114 +    return ::GetLastError();
   1.115 +
   1.116 +  return ERROR_SUCCESS;
   1.117 +}
   1.118 +
   1.119 +}  // namespace sandbox

mercurial