[m-rev.] diff: make_temp_directory now improves security for mono on POSIX-like OSs

Paul Bone paul at bone.id.au
Mon May 2 12:00:54 AEST 2016


From: Sebastian Godelet <sebastian.godelet at outlook.com>

make_temp_directory now improves security for mono on POSIX-like OSs

library/io.m:
    The make_temp_directory code for C# now supports both mono on POSIX and
    .NET on Windows.  It executes different code on different platforms to
    set permissions correctly.
---
 library/io.m | 90 ++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 60 insertions(+), 30 deletions(-)

diff --git a/library/io.m b/library/io.m
index 6497f44..3b96cef 100644
--- a/library/io.m
+++ b/library/io.m
@@ -1892,6 +1892,7 @@
 :- pragma foreign_decl("C#", "
 using System;
 using System.IO;
+using System.Runtime.InteropServices;
 using System.Security.AccessControl;
 using System.Security.Principal;
 ").
@@ -1927,6 +1928,13 @@ using System.Security.Principal;
     // a byte order mark.
     static readonly System.Text.Encoding text_encoding =
         new System.Text.UTF8Encoding(false);
+
+#if __MonoCS__
+    // int chmod(const char *path, mode_t mode);
+    [DllImport(""libc"", SetLastError=true, EntryPoint=""mkdir"",
+        CallingConvention=CallingConvention.Cdecl)]
+    static extern int ML_sys_mkdir (string path, uint mode);
+#endif
 ").
 
 :- pragma foreign_code("Java",
@@ -10762,43 +10770,65 @@ import java.util.Random;
         DirName::out, Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
     [will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
 "{
-    try {
-        DateTime utcNow = DateTime.UtcNow;
+    try
+    {
         DirName = Path.Combine(Dir, Path.GetRandomFileName());
 
-        // obtain the owner of the temporary directory, on any recent system
-        // this should be the current user, should work on any platform
-        // supporting .NET 2.0 or later
-        IdentityReference currentUser =
-            new DirectoryInfo(Dir).GetAccessControl(AccessControlSections.Owner)
-                                  .GetOwner(typeof(SecurityIdentifier));
-
-        DirectorySecurity security = new DirectorySecurity();
-        // Make the directory only accessible by the current user
-        security.AddAccessRule(new FileSystemAccessRule(currentUser,
-            FileSystemRights.ListDirectory |
-            FileSystemRights.Read |
-            FileSystemRights.Modify,
-            InheritanceFlags.None,
-            PropagationFlags.None,
-            AccessControlType.Allow));
-
-        DirectoryInfo TempDirInfo = Directory.CreateDirectory(DirName, security);
-        // Check if this was really created by us
-        if (TempDirInfo.CreationTimeUtc >= utcNow)
-        {
-            Okay = mr_bool.YES;
-            ErrorMessage = """";
-        }
-        else
+        switch (Environment.OSVersion.Platform)
         {
-            Okay = mr_bool.NO;
-            ErrorMessage = string.Format(""{0} already exists"", DirName);
+            case PlatformID.Win32NT:
+                // obtain the owner of the temporary directory
+                IdentityReference tempInfo =
+                    new DirectoryInfo(Dir)
+                        .GetAccessControl(AccessControlSections.Owner)
+                        .GetOwner(typeof(SecurityIdentifier));
+
+                DirectorySecurity security = new DirectorySecurity();
+                security.AddAccessRule(
+                    new FileSystemAccessRule(tempInfo,
+                        FileSystemRights.ListDirectory
+                            | FileSystemRights.Read
+                            | FileSystemRights.Modify,
+                        InheritanceFlags.None,
+                        PropagationFlags.None,
+                        AccessControlType.Allow
+                    )
+                );
+                Directory.CreateDirectory(DirName, security);
+                ErrorMessage = string.Empty;
+                Okay = mr_bool.YES;
+                break;
+
+#if __MonoCS__
+            case PlatformID.Unix:
+            case (PlatformID)6: // MacOSX:
+                int errorNo = ML_sys_mkdir(DirName, 0x7 << 6);
+                if (errorNo == 0)
+                {
+                    ErrorMessage = string.Empty;
+                    Okay = mr_bool.YES;
+                }
+                else
+                {
+                    ErrorMessage = string.Format(
+                        ""Creating directory {0} failed with: {1:X}"",
+                            DirName, errorNo);
+                    Okay = mr_bool.NO;
+                }
+                break;
+#endif
+
+            default:
+                Okay = mr_bool.NO;
+                ErrorMessage =
+                    ""Changing folder permissions is not supported for: "" +
+                    Environment.OSVersion;
+                break;
         }
     }
     catch (System.Exception e)
     {
-        DirName = """";
+        DirName = string.Empty;
         Okay = mr_bool.NO;
         ErrorMessage = e.Message;
     }
-- 
2.8.1



More information about the reviews mailing list