This is an automated email from the ASF dual-hosted git repository.

stigahuang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit d4707ff1973255ed29f2d7b7740d809f26d80703
Author: Arnab Karmakar <[email protected]>
AuthorDate: Tue Nov 25 15:00:43 2025 +0530

    IMPALA-13941: Add helper to format file permissions as UNIX-style string
    
    This change introduces a utility method FormatPermissions() that
    converts mode_t permission bits into a human-readable string
    (e.g., "drwxrwxrwt"). It correctly handles file type indicators,
    owner/group/other read-write-execute bits, and special bits
    such as setuid, setgid, and sticky.
    
    This improves log readability and debugging for file metadata-related
    operations by providing consistent, ls-style permission formatting.
    
    Testing:
    - Added unit tests validating permission string output for:
      - Regular files, directories, symlinks, sockets
      - All rwx combinations for user/group/other
      - setuid, setgid, and sticky bit behavior
    
    Change-Id: Ib53dbecd5c202e33b6e3b5cd3a372a77d8b1703a
    Reviewed-on: http://gerrit.cloudera.org:8080/23714
    Reviewed-by: Riza Suminto <[email protected]>
    Reviewed-by: Michael Smith <[email protected]>
    Tested-by: Michael Smith <[email protected]>
---
 be/src/rpc/authentication-test.cc | 70 +++++++++++++++++++++++++++++++++++++++
 be/src/rpc/authentication.cc      | 42 +++++++++++++++++++++--
 2 files changed, 109 insertions(+), 3 deletions(-)

diff --git a/be/src/rpc/authentication-test.cc 
b/be/src/rpc/authentication-test.cc
index 308e8d55c..7df006a21 100644
--- a/be/src/rpc/authentication-test.cc
+++ b/be/src/rpc/authentication-test.cc
@@ -61,6 +61,9 @@ int SaslAuthorizeInternal(sasl_conn_t* conn, void* context,
     const char* def_realm, unsigned urlen,
     struct propctx* propctx);
 
+// Expose the FormatPermissions function for testing
+string FormatPermissions(mode_t mode);
+
 TEST(Auth, PrincipalSubstitution) {
   string hostname;
   ASSERT_OK(GetHostname(&hostname));
@@ -388,6 +391,73 @@ TEST(Auth, UserUtilities) {
   }
 }
 
+// Test for IMPALA-13941: FormatPermissions correctly formats file permissions
+TEST(Auth, FormatPermissions) {
+  // Test directory with standard /var/tmp permissions (01777 = drwxrwxrwt)
+  mode_t mode = S_IFDIR | 01777;
+  ASSERT_EQ("drwxrwxrwt", FormatPermissions(mode));
+
+  // Test directory with common permissions (0755 = drwxr-xr-x)
+  mode = S_IFDIR | 0755;
+  ASSERT_EQ("drwxr-xr-x", FormatPermissions(mode));
+
+  // Test directory with restricted permissions (0700 = drwx------)
+  mode = S_IFDIR | 0700;
+  ASSERT_EQ("drwx------", FormatPermissions(mode));
+
+  // Test directory with sticky bit but not world-writable (01755 = drwxr-xr-t)
+  mode = S_IFDIR | 01755;
+  ASSERT_EQ("drwxr-xr-t", FormatPermissions(mode));
+
+  // Test regular file with common permissions (0644 = -rw-r--r--)
+  mode = S_IFREG | 0644;
+  ASSERT_EQ("-rw-r--r--", FormatPermissions(mode));
+
+  // Test executable file (0755 = -rwxr-xr-x)
+  mode = S_IFREG | 0755;
+  ASSERT_EQ("-rwxr-xr-x", FormatPermissions(mode));
+
+  // Test file with setuid bit (04755 = -rwsr-xr-x)
+  mode = S_IFREG | S_ISUID | 0755;
+  ASSERT_EQ("-rwsr-xr-x", FormatPermissions(mode));
+
+  // Test file with setgid bit (02755 = -rwxr-sr-x)
+  mode = S_IFREG | S_ISGID | 0755;
+  ASSERT_EQ("-rwxr-sr-x", FormatPermissions(mode));
+
+  // Test file with setuid but no execute (04644 = -rwSr--r--)
+  mode = S_IFREG | S_ISUID | 0644;
+  ASSERT_EQ("-rwSr--r--", FormatPermissions(mode));
+
+  // Test symbolic link (0777 = lrwxrwxrwx)
+  mode = S_IFLNK | 0777;
+  ASSERT_EQ("lrwxrwxrwx", FormatPermissions(mode));
+
+  // Test block device (0660 = brw-rw----)
+  mode = S_IFBLK | 0660;
+  ASSERT_EQ("brw-rw----", FormatPermissions(mode));
+
+  // Test character device (0666 = crw-rw-rw-)
+  mode = S_IFCHR | 0666;
+  ASSERT_EQ("crw-rw-rw-", FormatPermissions(mode));
+
+  // Test FIFO/pipe (0644 = prw-r--r--)
+  mode = S_IFIFO | 0644;
+  ASSERT_EQ("prw-r--r--", FormatPermissions(mode));
+
+  // Test socket (0755 = srwxr-xr-x)
+  mode = S_IFSOCK | 0755;
+  ASSERT_EQ("srwxr-xr-x", FormatPermissions(mode));
+
+  // Test no permissions (0000 = d---------)
+  mode = S_IFDIR | 0000;
+  ASSERT_EQ("d---------", FormatPermissions(mode));
+
+  // Test sticky bit without execute (01776 = drwxrwxrwT)
+  mode = S_IFDIR | 01776;
+  ASSERT_EQ("drwxrwxrwT", FormatPermissions(mode));
+}
+
 }
 int main(int argc, char** argv) {
   ::testing::InitGoogleTest(&argc, argv);
diff --git a/be/src/rpc/authentication.cc b/be/src/rpc/authentication.cc
index 8a879d57f..a282ac1fe 100644
--- a/be/src/rpc/authentication.cc
+++ b/be/src/rpc/authentication.cc
@@ -1237,6 +1237,41 @@ Status InitAuth(const string& appname) {
   return Status::OK();
 }
 
+// Helper function to format file permissions as a string (e.g., "drwxrwxrwt").
+string FormatPermissions(mode_t mode) {
+  string result(10, '-');
+
+  // File type
+  if (S_ISDIR(mode)) result[0] = 'd';
+  else if (S_ISLNK(mode)) result[0] = 'l';
+  else if (S_ISBLK(mode)) result[0] = 'b';
+  else if (S_ISCHR(mode)) result[0] = 'c';
+  else if (S_ISFIFO(mode)) result[0] = 'p';
+  else if (S_ISSOCK(mode)) result[0] = 's';
+
+  // Owner permissions
+  if (mode & S_IRUSR) result[1] = 'r';
+  if (mode & S_IWUSR) result[2] = 'w';
+  if (mode & S_IXUSR) result[3] = 'x';
+
+  // Group permissions
+  if (mode & S_IRGRP) result[4] = 'r';
+  if (mode & S_IWGRP) result[5] = 'w';
+  if (mode & S_IXGRP) result[6] = 'x';
+
+  // Other permissions
+  if (mode & S_IROTH) result[7] = 'r';
+  if (mode & S_IWOTH) result[8] = 'w';
+  if (mode & S_IXOTH) result[9] = 'x';
+
+  // Special bits (setuid, setgid, sticky)
+  if (mode & S_ISUID) result[3] = (mode & S_IXUSR) ? 's' : 'S';
+  if (mode & S_ISGID) result[6] = (mode & S_IXGRP) ? 's' : 'S';
+  if (mode & S_ISVTX) result[9] = (mode & S_IXOTH) ? 't' : 'T';
+
+  return result;
+}
+
 // Ensure that /var/tmp (the location of the Kerberos replay cache) has 
drwxrwxrwt
 // permissions.  If it doesn't, Kerberos will be unhappy in a way that's very 
difficult
 // to debug.  We do this using direct stat() calls because boost doesn't 
support the
@@ -1254,9 +1289,10 @@ Status CheckReplayCacheDirPermissions() {
   }
 
   if ((st.st_mode & 01777) != 01777) {
-    return Status("Error: The permissions on /var/tmp must precisely match "
-        "\"drwxrwxrwt\". This directory is used by the Kerberos replay cache. 
To "
-        "rectify this issue, run \"chmod 01777 /var/tmp\" as root.");
+    return Status(Substitute("Error: The permissions on /var/tmp must 
precisely match "
+        "\"drwxrwxrwt\". This directory is used by the Kerberos replay cache. "
+        "Current permissions: \"$0\". To rectify this issue, run "
+        "\"chmod 01777 /var/tmp\" as root.", FormatPermissions(st.st_mode)));
   }
 
   return Status::OK();

Reply via email to