]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
test: Add test for semantics
authorChristopher Hoffman <choffman@redhat.com>
Mon, 4 Dec 2023 14:22:04 +0000 (14:22 +0000)
committerChristopher Hoffman <choffman@redhat.com>
Wed, 5 Nov 2025 13:59:33 +0000 (13:59 +0000)
Signed-off-by: Christopher Hoffman <choffman@redhat.com>
src/test/libcephfs/fscrypt.cc

index 027e6340e20a9c5b2c5ab2818dae1d9b042b8dcf..4aa89a514fc726623797b1bb728ab35d8ec41752 100644 (file)
@@ -356,7 +356,7 @@ TEST(FSCrypt, SetPolicyEmptyDir) {
   ceph_shutdown(cmount);
 }
 
-TEST(FSCrypt, SetPolicyNotEmptyFile) {
+TEST(FSCrypt, SetPolicyNotEmptyDir) {
   struct ceph_fscrypt_key_identifier kid;
 
   struct ceph_mount_info* cmount;
@@ -365,6 +365,8 @@ TEST(FSCrypt, SetPolicyNotEmptyFile) {
 
   string dir_path = "dir1";
   ceph_mkdir(cmount, dir_path.c_str(), 0777);
+  string dir2_path = "dir1/dir2";
+  ceph_mkdir(cmount, dir2_path.c_str(), 0777);
 
   string file_path = "dir1/file1";
   int fd = ceph_open(cmount, file_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
@@ -397,24 +399,91 @@ TEST(FSCrypt, SetPolicyNotEmptyFile) {
   ceph_shutdown(cmount);
 }
 
-TEST(FSCrypt, SetPolicyNotEmptyDir) {
+TEST(FSCrypt, SetPolicyAlreadyExistSameKey) {
   struct ceph_fscrypt_key_identifier kid;
 
   struct ceph_mount_info* cmount;
   int r = init_mount(&cmount);
   ASSERT_EQ(0, r);
 
-  string dir_path = "dir1";
+  string dir_path = "dir2";
   ceph_mkdir(cmount, dir_path.c_str(), 0777);
-  string dir2_path = "dir1/dir2";
-  ceph_mkdir(cmount, dir2_path.c_str(), 0777);
 
-  string file_path = "dir1/file1";
+  int fd = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
+
+  r = ceph_add_fscrypt_key(cmount, fscrypt_key, sizeof(fscrypt_key), &kid, 1299);
+
+  struct fscrypt_policy_v2 policy;
+  policy.version = 2;
+  policy.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
+  policy.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
+  policy.flags = FSCRYPT_POLICY_FLAGS_PAD_32;
+  memcpy(policy.master_key_identifier, kid.raw, FSCRYPT_KEY_IDENTIFIER_SIZE);
+
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+  ASSERT_EQ(0, r);
+
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+  ASSERT_EQ(-EEXIST, r);
+
+  ceph_rmdir(cmount, dir_path.c_str());
+  ceph_shutdown(cmount);
+}
+
+TEST(FSCrypt, SetPolicyNonDir) {
+  //can be file, symlink, device file etc
+  struct ceph_fscrypt_key_identifier kid;
+
+  struct ceph_mount_info* cmount;
+  int r = init_mount(&cmount);
+  ASSERT_EQ(0, r);
+
+  //setup policy
+  struct fscrypt_policy_v2 policy;
+  policy.version = 2;
+  policy.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
+  policy.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
+  policy.flags = FSCRYPT_POLICY_FLAGS_PAD_32;
+  memcpy(policy.master_key_identifier, kid.raw, FSCRYPT_KEY_IDENTIFIER_SIZE);
+
+  //file
+  string file_path = "file1";
   int fd = ceph_open(cmount, file_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
-  r = ceph_write(cmount, fd, fscrypt_key, sizeof(fscrypt_key), 0);
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+  ASSERT_EQ(-ENOTDIR, r);
   ceph_close(cmount, fd);
 
-  int fd2 = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
+  //symlink
+  string symlink_path = "symlink1";
+  r = ceph_symlink(cmount, file_path.c_str(), symlink_path.c_str());
+  fd = ceph_open(cmount, symlink_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+  ASSERT_EQ(-ENOTDIR, r);
+  ceph_close(cmount, fd);
+
+  //device file
+  string mknod_path = "device1";
+  r = ceph_mknod(cmount, mknod_path.c_str(), 0600, 55);
+  fd = ceph_open(cmount, mknod_path.c_str(), O_RDWR, 0600);
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+  ASSERT_EQ(-ENOTDIR, r);
+  ceph_close(cmount, fd);
+
+  ceph_shutdown(cmount);
+}
+
+TEST(FSCrypt, LockedListDir) {
+  struct ceph_fscrypt_key_identifier kid;
+
+  struct ceph_mount_info* cmount;
+  int r = init_mount(&cmount);
+  ASSERT_EQ(0, r);
+
+  string dir_path = "dir1";
+  ceph_mkdir(cmount, dir_path.c_str(), 0777);
+
+  string file_path = "dir1/file5";
+  int fd = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
 
   r = ceph_add_fscrypt_key(cmount, fscrypt_key, sizeof(fscrypt_key), &kid, 1299);
 
@@ -425,9 +494,24 @@ TEST(FSCrypt, SetPolicyNotEmptyDir) {
   policy.flags = FSCRYPT_POLICY_FLAGS_PAD_32;
   memcpy(policy.master_key_identifier, kid.raw, FSCRYPT_KEY_IDENTIFIER_SIZE);
 
-  r = ceph_set_fscrypt_policy_v2(cmount, fd2, &policy);
-  ASSERT_EQ(-ENOTEMPTY, r);
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+
+  int fd2 = ceph_open(cmount, file_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
+  r = ceph_write(cmount, fd2, fscrypt_key, sizeof(fscrypt_key), 0);
+  ASSERT_EQ(32, r);
 
+  ceph_close(cmount, fd);
+  ceph_close(cmount, fd2);
+
+  ino_t inode = 0;
+  struct ceph_dir_result *rdir;
+  struct dirent *result;
+  ASSERT_EQ(ceph_opendir(cmount, "dir1", &rdir), 0);
+  while ((result = ceph_readdir(cmount, rdir)) != NULL) {
+    if (strcmp(result->d_name, "file5") == 0) {
+      inode = result->d_ino;
+    }
+  }
   fscrypt_remove_key_arg arg;
   generate_remove_key_arg(kid, &arg);
 
@@ -435,21 +519,40 @@ TEST(FSCrypt, SetPolicyNotEmptyDir) {
   ASSERT_EQ(0, r);
   ASSERT_EQ(0, arg.removal_status_flags);
 
+  ASSERT_EQ(ceph_opendir(cmount, "dir1", &rdir), 0);
+  while ((result = ceph_readdir(cmount, rdir)) != NULL) {
+    if (result->d_ino == inode){
+      file_path = dir_path;
+      file_path.append("/");
+      file_path.append(result->d_name);
+
+      //check that we can get stat info
+      struct stat st;
+      ceph_stat(cmount, file_path.c_str(), &st);
+
+      ASSERT_EQ(sizeof(fscrypt_key), st.st_size);
+      goto done;
+    }
+  }
+  ASSERT_EQ(0,-1); //will fail
+
+done:
   ceph_unlink(cmount, file_path.c_str());
   ceph_rmdir(cmount, dir_path.c_str());
   ceph_shutdown(cmount);
 }
 
-TEST(FSCrypt, SetPolicyAlreadyExistSameKey) {
+TEST(FSCrypt, ReadLockedDir) {
   struct ceph_fscrypt_key_identifier kid;
 
   struct ceph_mount_info* cmount;
   int r = init_mount(&cmount);
   ASSERT_EQ(0, r);
-  
-  string dir_path = "dir2";
+
+  string dir_path = "dir1";
   ceph_mkdir(cmount, dir_path.c_str(), 0777);
 
+  string file_path = "dir1/file5";
   int fd = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
 
   r = ceph_add_fscrypt_key(cmount, fscrypt_key, sizeof(fscrypt_key), &kid, 1299);
@@ -462,25 +565,205 @@ TEST(FSCrypt, SetPolicyAlreadyExistSameKey) {
   memcpy(policy.master_key_identifier, kid.raw, FSCRYPT_KEY_IDENTIFIER_SIZE);
 
   r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+
+  int fd2 = ceph_open(cmount, file_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
+  r = ceph_write(cmount, fd2, fscrypt_key, sizeof(fscrypt_key), 0);
+  ASSERT_EQ(32, r);
+
+  ceph_close(cmount, fd);
+  ceph_close(cmount, fd2);
+
+  ino_t inode = 0;
+  struct ceph_dir_result *rdir;
+  struct dirent *result;
+  ASSERT_EQ(ceph_opendir(cmount, "dir1", &rdir), 0);
+  while ((result = ceph_readdir(cmount, rdir)) != NULL) {
+    if (strcmp(result->d_name, "file5") == 0) {
+      inode = result->d_ino;
+    }
+  }
+  fscrypt_remove_key_arg arg;
+  generate_remove_key_arg(kid, &arg);
+
+  r = ceph_remove_fscrypt_key(cmount, &arg, 1299);
+  ASSERT_EQ(0, r);
+  ASSERT_EQ(0, arg.removal_status_flags);
+
+  ASSERT_EQ(ceph_opendir(cmount, "dir1", &rdir), 0);
+  while ((result = ceph_readdir(cmount, rdir)) != NULL) {
+    if (result->d_ino == inode){
+      file_path = dir_path;
+      file_path.append("/");
+      file_path.append(result->d_name);
+      goto read;
+    }
+  }
+  ASSERT_EQ(0,-1); //will fail
+
+read:
+  fd2 = ceph_open(cmount, file_path.c_str(), O_RDWR, 0600);
+  ASSERT_EQ(-ENOKEY, fd2);
+
+  ceph_unlink(cmount, file_path.c_str());
+  ceph_rmdir(cmount, dir_path.c_str());
+  ceph_shutdown(cmount);
+}
+
+TEST(FSCrypt, WriteLockedDir) {
+  struct ceph_fscrypt_key_identifier kid;
+
+  struct ceph_mount_info* cmount;
+  int r = init_mount(&cmount);
   ASSERT_EQ(0, r);
 
+  string dir_path = "dir1";
+  string dir_path2 = "dir1/dir3";
+  ceph_mkdir(cmount, dir_path.c_str(), 0777);
+
+  string file_path = "dir1/file5";
+  int fd = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
+
+  r = ceph_add_fscrypt_key(cmount, fscrypt_key, sizeof(fscrypt_key), &kid, 1299);
+
+  struct fscrypt_policy_v2 policy;
+  policy.version = 2;
+  policy.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
+  policy.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
+  policy.flags = FSCRYPT_POLICY_FLAGS_PAD_32;
+  memcpy(policy.master_key_identifier, kid.raw, FSCRYPT_KEY_IDENTIFIER_SIZE);
+
   r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
-  ASSERT_EQ(-EEXIST, r);
-  
+
+  int fd2 = ceph_open(cmount, file_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
+  r = ceph_write(cmount, fd2, fscrypt_key, sizeof(fscrypt_key), 0);
+  ASSERT_EQ(32, r);
+
+  ceph_close(cmount, fd);
+  ceph_close(cmount, fd2);
+
+  ino_t inode = 0;
+  struct ceph_dir_result *rdir;
+  struct dirent *result;
+  ASSERT_EQ(ceph_opendir(cmount, "dir1", &rdir), 0);
+  while ((result = ceph_readdir(cmount, rdir)) != NULL) {
+    if (strcmp(result->d_name, "file5") == 0) {
+      inode = result->d_ino;
+    }
+  }
+  fscrypt_remove_key_arg arg;
+  generate_remove_key_arg(kid, &arg);
+
+  r = ceph_remove_fscrypt_key(cmount, &arg, 1299);
+  ASSERT_EQ(0, r);
+  ASSERT_EQ(0, arg.removal_status_flags);
+
+  ASSERT_EQ(ceph_opendir(cmount, "dir1", &rdir), 0);
+  while ((result = ceph_readdir(cmount, rdir)) != NULL) {
+    if (result->d_ino == inode){
+      file_path = dir_path;
+      file_path.append("/");
+      file_path.append(result->d_name);
+      goto write;
+    }
+  }
+  ASSERT_EQ(0,-1); //will fail
+
+write:
+  fd2 = ceph_open(cmount, file_path.c_str(), O_RDWR, 0600);
+  ASSERT_EQ(-ENOKEY, fd2);
+
+  ASSERT_EQ(-ENOKEY, ceph_mkdir(cmount, dir_path2.c_str(), 0777));
+
+  ceph_unlink(cmount, file_path.c_str());
   ceph_rmdir(cmount, dir_path.c_str());
   ceph_shutdown(cmount);
 }
 
-TEST(FSCrypt, SetPolicyNonDir) {
-  //can be file, symlink, hardlink, device file etc
+TEST(FSCrypt, LockedCreateSnap) {
   struct ceph_fscrypt_key_identifier kid;
 
   struct ceph_mount_info* cmount;
   int r = init_mount(&cmount);
   ASSERT_EQ(0, r);
 
+  string dir_path = "dir1";
+  ceph_mkdir(cmount, dir_path.c_str(), 0777);
+
+  string file_path = "dir1/file5";
+  int fd = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
+
   r = ceph_add_fscrypt_key(cmount, fscrypt_key, sizeof(fscrypt_key), &kid, 1299);
-  ASSERT_EQ(-ENOTDIR, r);
+
+  struct fscrypt_policy_v2 policy;
+  policy.version = 2;
+  policy.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
+  policy.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
+  policy.flags = FSCRYPT_POLICY_FLAGS_PAD_32;
+  memcpy(policy.master_key_identifier, kid.raw, FSCRYPT_KEY_IDENTIFIER_SIZE);
+
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+
+  int fd2 = ceph_open(cmount, file_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
+  r = ceph_write(cmount, fd2, fscrypt_key, sizeof(fscrypt_key), 0);
+  ASSERT_EQ(32, r);
+
+  ceph_close(cmount, fd);
+  ceph_close(cmount, fd2);
+
+  fscrypt_remove_key_arg arg;
+  generate_remove_key_arg(kid, &arg);
+
+  r = ceph_remove_fscrypt_key(cmount, &arg, 1299);
+  ASSERT_EQ(0, r);
+  ASSERT_EQ(0, arg.removal_status_flags);
+
+  string snap_name = "snap1";
+  ASSERT_EQ(-ENOKEY, ceph_mksnap(cmount, dir_path.c_str(), snap_name.c_str(), 0755, nullptr, 0));
+  ceph_unlink(cmount, file_path.c_str());
+  ceph_rmdir(cmount, dir_path.c_str());
+  ceph_shutdown(cmount);
+}
+
+TEST(FSCrypt, RenameLockedSource) {
+  struct ceph_fscrypt_key_identifier kid;
+
+  struct ceph_mount_info* cmount;
+  int r = init_mount(&cmount);
+  ASSERT_EQ(0, r);
+
+  string dir_path = "dir1";
+  ceph_mkdir(cmount, dir_path.c_str(), 0777);
+
+  string src_path = "dir1/file5";
+  int fd = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
+
+  r = ceph_add_fscrypt_key(cmount, fscrypt_key, sizeof(fscrypt_key), &kid, 1299);
+
+  struct fscrypt_policy_v2 policy;
+  policy.version = 2;
+  policy.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
+  policy.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
+  policy.flags = FSCRYPT_POLICY_FLAGS_PAD_32;
+  memcpy(policy.master_key_identifier, kid.raw, FSCRYPT_KEY_IDENTIFIER_SIZE);
+
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+
+  int fd2 = ceph_open(cmount, src_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
+  r = ceph_write(cmount, fd2, fscrypt_key, sizeof(fscrypt_key), 0);
+  ASSERT_EQ(32, r);
+
+  ceph_close(cmount, fd);
+  ceph_close(cmount, fd2);
+
+  ino_t inode = 0;
+  struct ceph_dir_result *rdir;
+  struct dirent *result;
+  ASSERT_EQ(ceph_opendir(cmount, "dir1", &rdir), 0);
+  while ((result = ceph_readdir(cmount, rdir)) != NULL) {
+    if (strcmp(result->d_name, "file5") == 0) {
+      inode = result->d_ino;
+    }
+  }
 
   fscrypt_remove_key_arg arg;
   generate_remove_key_arg(kid, &arg);
@@ -489,6 +772,69 @@ TEST(FSCrypt, SetPolicyNonDir) {
   ASSERT_EQ(0, r);
   ASSERT_EQ(0, arg.removal_status_flags);
 
+  ASSERT_EQ(ceph_opendir(cmount, "dir1", &rdir), 0);
+  while ((result = ceph_readdir(cmount, rdir)) != NULL) {
+    if (result->d_ino == inode){
+      src_path = dir_path;
+      src_path.append("/");
+      src_path.append(result->d_name);
+      break;
+    }
+  }
+  ASSERT_EQ(ceph_closedir(cmount, rdir), 0);
+
+  string dest_path = "file_dest";
+
+  ASSERT_EQ(ceph_rename(cmount, src_path.c_str(), dest_path.c_str()), -ENOKEY);
+
+  ceph_unlink(cmount, src_path.c_str());
+  ceph_rmdir(cmount, dir_path.c_str());
+  ceph_shutdown(cmount);
+}
+
+TEST(FSCrypt, RenameLockedDest) {
+  struct ceph_fscrypt_key_identifier kid;
+
+  struct ceph_mount_info* cmount;
+  int r = init_mount(&cmount);
+  ASSERT_EQ(0, r);
+
+  string dir_path = "dir1";
+  ceph_mkdir(cmount, dir_path.c_str(), 0777);
+
+  string src_path = "file_src";
+  string dest_path = "dir1/file_dest";
+  int fd = ceph_open(cmount, dir_path.c_str(), O_DIRECTORY, 0);
+
+  r = ceph_add_fscrypt_key(cmount, fscrypt_key, sizeof(fscrypt_key), &kid, 1299);
+
+  struct fscrypt_policy_v2 policy;
+  policy.version = 2;
+  policy.contents_encryption_mode = FSCRYPT_MODE_AES_256_XTS;
+  policy.filenames_encryption_mode = FSCRYPT_MODE_AES_256_CTS;
+  policy.flags = FSCRYPT_POLICY_FLAGS_PAD_32;
+  memcpy(policy.master_key_identifier, kid.raw, FSCRYPT_KEY_IDENTIFIER_SIZE);
+
+  r = ceph_set_fscrypt_policy_v2(cmount, fd, &policy);
+
+  int fd2 = ceph_open(cmount, src_path.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0600);
+  r = ceph_write(cmount, fd2, fscrypt_key, sizeof(fscrypt_key), 0);
+  ASSERT_EQ(32, r);
+
+  ceph_close(cmount, fd);
+  ceph_close(cmount, fd2);
+
+  fscrypt_remove_key_arg arg;
+  generate_remove_key_arg(kid, &arg);
+
+  r = ceph_remove_fscrypt_key(cmount, &arg, 1299);
+  ASSERT_EQ(0, r);
+  ASSERT_EQ(0, arg.removal_status_flags);
+
+  ASSERT_EQ(ceph_rename(cmount, src_path.c_str(), dest_path.c_str()), -ENOKEY);
+
+  ceph_unlink(cmount, src_path.c_str());
+  ceph_rmdir(cmount, dir_path.c_str());
   ceph_shutdown(cmount);
 }