title: SetSecurityInfo returns access denied
body: <p>Using C, I'm trying to establish a pipe connection between a process and it's child process, while the child process has a lower mandatory(integrity) level (low, while the parent process is high).</p>
  
  <p>I wrote the following program (it's a simplified version if it), but it fails with: <code>ERROR_ACCESS_DENIED (0x5)</code></p>
  
  <pre><code>INT wmain(IN SIZE_T nArgc, IN PWSTR *pArgv)
  {
      SECURITY_ATTRIBUTES securityArrtibutes = { 0 };
      HANDLE hPipeRead = NULL;
      HANDLE hPipeWrite = NULL;
  
      tSecurityArrtibutes.nLength = sizeof(tSecurityArrtibutes);
      tSecurityArrtibutes.bInheritHandle = TRUE;
  
      SetSeSecurityNamePrivilege();
      CreatePipe(&amp;hPipeRead, &amp;hPipeWrite, &amp;securityArrtibutes, 0);
      ChangeMandatoryLabelHandle(hPipeRead);
  }
  
  VOID ChangeMandatoryLabelHandle(HANDLE hObject)
  {
      BOOL bRetval = FALSE;
      DWORD dwError = 0;
      PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
      PACL ptSacl = NULL;
      BOOL bSaclPresent = FALSE;
      BOOL bSaclDefaulted = FALSE;
      PWSTR pSDDL = NULL;
  
      SDDL = L"S:(ML;;LW;;;NW)";
  
      bRetval = ConvertStringSecurityDescriptorToSecurityDescriptorW(pSDDL, SDDL_REVISION_1, &amp;pSecurityDescriptor, NULL);
      if (FALSE == bRetval)
          ... // Handle failure
  
      bRetval = GetSecurityDescriptorSacl(pSecurityDescriptor, &amp;bSaclPresent, &amp;ptSacl, &amp;bSaclDefaulted);
      if (FALSE == bRetval)
          ... // Handle failure
  
      // getting ERROR_ACCESS_DENIED (0x5)
      dwErr = SetSecurityInfo(hObject, SE_KERNEL_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, ptSacl);
      if (ERROR_SUCCESS != dwErr)
          ... // Handle failure
  
      ... // Cleanup
  }
  </code></pre>
  
  <p>I followed <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa379588(v=vs.85).aspx" rel="nofollow noreferrer">https://msdn.microsoft.com/en-us/library/windows/desktop/aa379588(v=vs.85).aspx</a> and the remark that 
  <code>To set the SACL of an object, the caller must have the SE_SECURITY_NAME privilege enabled.</code> :</p>
  
  <pre><code>BOOL SetSeSecurityNamePrivilege()
  {
      HANDLE hToken;
      TOKEN_PRIVILEGES tp;
      LUID luid;
  
      if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_IMPERSONATE, &amp;hToken)
          return FALSE
  
      if (!LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &amp;luid))
          return FALSE;
  
      tp.PrivilegeCount = 1;
      tp.Privileges[0].Luid = luid;
      if (bEnablePrivilege)
          tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
      else
          tp.Privileges[0].Attributes = 0;
  
      if (!AdjustTokenPrivileges(hToken, FALSE, &amp;tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL))
          return FALSE;
  
      if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
          return FALSE;
  
      return TRUE;
  }
  </code></pre>
  
  <p>note: I get the same result when I try to execute it with files, with <code>CreateFile</code> instead of <code>CreatePipe</code>.
  In addition if I try to do that with files, and I replace <code>SetSecurityInfo</code> with <code>SetNamedSecurityInfoW</code>, and give it the full path of the file, it works great.</p>
  
  <p>Does anyone have an idea how to make it work? Thanks!</p>