15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/job.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/restricted_token.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Job::~Job() {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (job_handle_)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::CloseHandle(job_handle_);
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)DWORD Job::Init(JobLevel security_level,
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                const wchar_t* job_name,
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                DWORD ui_exceptions,
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                size_t memory_limit) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (job_handle_)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERROR_ALREADY_INITIALIZED;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job_handle_ = ::CreateJobObject(NULL,   // No security attribute
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  job_name);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!job_handle_)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ::GetLastError();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JOBOBJECT_BASIC_UI_RESTRICTIONS jbur = {0};
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the settings for the different security levels. Note: The higher levels
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inherit from the lower levels.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (security_level) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JOB_LOCKDOWN: {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jeli.BasicLimitInformation.LimitFlags |=
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JOB_RESTRICTED: {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_READCLIPBOARD;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_GLOBALATOMS;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JOB_LIMITED_USER: {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jeli.BasicLimitInformation.ActiveProcessLimit = 1;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JOB_INTERACTIVE: {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_DESKTOP;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jbur.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case JOB_UNPROTECTED: {
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (memory_limit) {
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        jeli.BasicLimitInformation.LimitFlags |=
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            JOB_OBJECT_LIMIT_PROCESS_MEMORY;
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        jeli.ProcessMemoryLimit = memory_limit;
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jeli.BasicLimitInformation.LimitFlags |=
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default: {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERROR_BAD_ARGUMENTS;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FALSE == ::SetInformationJobObject(job_handle_,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         JobObjectExtendedLimitInformation,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &jeli,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         sizeof(jeli))) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ::GetLastError();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jbur.UIRestrictionsClass = jbur.UIRestrictionsClass & (~ui_exceptions);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FALSE == ::SetInformationJobObject(job_handle_,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         JobObjectBasicUIRestrictions,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         &jbur,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         sizeof(jbur))) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ::GetLastError();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERROR_SUCCESS;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD Job::UserHandleGrantAccess(HANDLE handle) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!job_handle_)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERROR_NO_DATA;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::UserHandleGrantAccess(handle,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               job_handle_,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               TRUE)) {  // Access allowed.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ::GetLastError();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERROR_SUCCESS;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HANDLE Job::Detach() {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE handle_temp = job_handle_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job_handle_ = NULL;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handle_temp;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD Job::AssignProcessToJob(HANDLE process_handle) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!job_handle_)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERROR_NO_DATA;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FALSE == ::AssignProcessToJobObject(job_handle_, process_handle))
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ::GetLastError();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERROR_SUCCESS;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
119