// Handles the creation of job objects based on a security profile. // Sample usage: // Job job; // job.Init(JOB_LOCKDOWN, nullptr); //no job name // job.AssignProcessToJob(process_handle); classJob { public: Job();
~Job();
// Initializes and creates the job object. The security of the job is based // on the security_level parameter. // job_name can be nullptr if the job is unnamed. // If the chosen profile has too many ui restrictions, you can disable some // by specifying them in the ui_exceptions parameters. // If the function succeeds, the return value is ERROR_SUCCESS. If the // function fails, the return value is the win32 error code corresponding to // the error. // job也是经典的constructor + init DWORD Init(JobLevel security_level, //决定Job对象安全级别,还记得chrome设定的JobLevel枚举量吗? constwchar_t* job_name, //名字可以没有,即匿名 DWORD ui_exceptions, //根据profile,个别UI限制可以开绿灯 size_t memory_limit); //应该是限制最大内存
// Assigns the process referenced by process_handle to the job. // If the function succeeds, the return value is ERROR_SUCCESS. If the // function fails, the return value is the win32 error code corresponding to // the error. // 把进程归属到Job对象,使用句柄HANDLE操控进程 // 注意此前在TargetProcess::Create中调用的是WinAPI AssignProcessToJobObject // 巧在该函数实际上也是对该API的封装,作为一个Job类的预留接口,我在跟踪代码时除了测试单元并没有发现其他地方对此接口引用 DWORD AssignProcessToJob(HANDLE process_handle);
// Grants access to "handle" to the job. All processes in the job can // subsequently recognize and use the handle. // If the function succeeds, the return value is ERROR_SUCCESS. If the // function fails, the return value is the win32 error code corresponding to // the error. //应该是调用之后,Job内的所有进程都可以访问传入的HANDLE DWORD UserHandleGrantAccess(HANDLE handle);
// Revokes ownership to the job handle and returns it. // If the object is not yet initialized, it returns an invalid handle. // 转移owner base::win::ScopedHandle Take();
private: // Handle to the job referenced by the object. base::win::ScopedHandle job_handle_; //看起来是引用Windows Job对象的成员
// Put this in the declarations for a class to be uncopyable and unassignable. #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ DISALLOW_COPY(TypeName); \ DISALLOW_ASSIGN(TypeName)
// Put this in the declarations for a class to be uncopyable. #define DISALLOW_COPY(TypeName) \ TypeName(const TypeName&) = delete
// Put this in the declarations for a class to be unassignable. #define DISALLOW_ASSIGN(TypeName) TypeName& operator=(const TypeName&) = delete
// The Job level specifies a set of decreasing security profiles for the // Job object that the target process will be placed into. // This table summarizes the security associated with each level: // // JobLevel |General |Quota | // |restrictions |restrictions | // -----------------|---------------------------------- |--------------------| // JOB_NONE | No job is assigned to the | None | // | sandboxed process. | | // -----------------|---------------------------------- |--------------------| // JOB_UNPROTECTED | None | *Kill on Job close.| // -----------------|---------------------------------- |--------------------| // JOB_INTERACTIVE | *Forbid system-wide changes using | | // | SystemParametersInfo(). | *Kill on Job close.| // | *Forbid the creation/switch of | | // | Desktops. | | // | *Forbids calls to ExitWindows(). | | // -----------------|---------------------------------- |--------------------| // JOB_LIMITED_USER | Same as INTERACTIVE_USER plus: | *One active process| // | *Forbid changes to the display | limit. | // | settings. | *Kill on Job close.| // -----------------|---------------------------------- |--------------------| // JOB_RESTRICTED | Same as LIMITED_USER plus: | *One active process| // | * No read/write to the clipboard. | limit. | // | * No access to User Handles that | *Kill on Job close.| // | belong to other processes. | | // | * Forbid message broadcasts. | | // | * Forbid setting global hooks. | | // | * No access to the global atoms | | // | table. | | // -----------------|-----------------------------------|--------------------| // JOB_LOCKDOWN | Same as RESTRICTED | *One active process| // | | limit. | // | | *Kill on Job close.| // | | *Kill on unhandled | // | | exception. | // | | | // In the context of the above table, 'user handles' refers to the handles of // windows, bitmaps, menus, etc. Files, treads and registry handles are kernel // handles and are not affected by the job level settings. enumJobLevel { JOB_LOCKDOWN = 0, JOB_RESTRICTED, JOB_LIMITED_USER, JOB_INTERACTIVE, JOB_UNPROTECTED, JOB_NONE };
// Helper structure that allows the Broker to associate a job notification // with a job object and with a policy. structJobTracker { JobTracker(base::win::ScopedHandle job, scoped_refptr<sandbox::PolicyBase> policy) : job(std::move(job)), policy(policy) {}// job owner再次转移给内部成员job ~JobTracker() { FreeResources(); }
// Releases the Job and notifies the associated Policy object to release its // resources as well. // 这才是关联policy的真实目的,在BrokerServicesBase::TargetEventsThread中可以看到 // JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO发生时,就要释放它的policy的资源 // 因为policy此时不再管辖任何target进程了 voidFreeResources();
voidJobTracker::FreeResources(){ if (policy) { // 先终止Job对象 bool res = ::TerminateJobObject(job.Get(), sandbox::SBOX_ALL_OK); DCHECK(res); // Closing the job causes the target process to be destroyed so this needs // to happen before calling OnJobEmpty(). HANDLE stale_job_handle = job.Get(); job.Close();
// In OnJobEmpty() we don't actually use the job handle directly. // 原来OnJobEmpty这个事件的驱动者在这儿 policy->OnJobEmpty(stale_job_handle); policy = nullptr; } }
// 揪出policy管理的targets_中,已经GG的target并删除 boolPolicyBase::OnJobEmpty(HANDLE job){ AutoLock lock(&lock_); TargetSet::iterator it; for (it = targets_.begin(); it != targets_.end(); ++it) { if ((*it)->Job() == job) break; } if (it == targets_.end()) { returnfalse; } TargetProcess* target = *it; targets_.erase(it); delete target; returntrue; }