cve-2021-47072
Vulnerability from cvelistv5
Published
2024-03-01 21:15
Modified
2024-12-19 07:34
Severity ?
Summary
In the Linux kernel, the following vulnerability has been resolved: btrfs: fix removed dentries still existing after log is synced When we move one inode from one directory to another and both the inode and its previous parent directory were logged before, we are not supposed to have the dentry for the old parent if we have a power failure after the log is synced. Only the new dentry is supposed to exist. Generally this works correctly, however there is a scenario where this is not currently working, because the old parent of the file/directory that was moved is not authoritative for a range that includes the dir index and dir item keys of the old dentry. This case is better explained with the following example and reproducer: # The test requires a very specific layout of keys and items in the # fs/subvolume btree to trigger the bug. So we want to make sure that # on whatever platform we are, we have the same leaf/node size. # # Currently in btrfs the node/leaf size can not be smaller than the page # size (but it can be greater than the page size). So use the largest # supported node/leaf size (64K). $ mkfs.btrfs -f -n 65536 /dev/sdc $ mount /dev/sdc /mnt # "testdir" is inode 257. $ mkdir /mnt/testdir $ chmod 755 /mnt/testdir # Create several empty files to have the directory "testdir" with its # items spread over several leaves (7 in this case). $ for ((i = 1; i <= 1200; i++)); do echo -n > /mnt/testdir/file$i done # Create our test directory "dira", inode number 1458, which gets all # its items in leaf 7. # # The BTRFS_DIR_ITEM_KEY item for inode 257 ("testdir") that points to # the entry named "dira" is in leaf 2, while the BTRFS_DIR_INDEX_KEY # item that points to that entry is in leaf 3. # # For this particular filesystem node size (64K), file count and file # names, we endup with the directory entry items from inode 257 in # leaves 2 and 3, as previously mentioned - what matters for triggering # the bug exercised by this test case is that those items are not placed # in leaf 1, they must be placed in a leaf different from the one # containing the inode item for inode 257. # # The corresponding BTRFS_DIR_ITEM_KEY and BTRFS_DIR_INDEX_KEY items for # the parent inode (257) are the following: # # item 460 key (257 DIR_ITEM 3724298081) itemoff 48344 itemsize 34 # location key (1458 INODE_ITEM 0) type DIR # transid 6 data_len 0 name_len 4 # name: dira # # and: # # item 771 key (257 DIR_INDEX 1202) itemoff 36673 itemsize 34 # location key (1458 INODE_ITEM 0) type DIR # transid 6 data_len 0 name_len 4 # name: dira $ mkdir /mnt/testdir/dira # Make sure everything done so far is durably persisted. $ sync # Now do a change to inode 257 ("testdir") that does not result in # COWing leaves 2 and 3 - the leaves that contain the directory items # pointing to inode 1458 (directory "dira"). # # Changing permissions, the owner/group, updating or adding a xattr, # etc, will not change (COW) leaves 2 and 3. So for the sake of # simplicity change the permissions of inode 257, which results in # updating its inode item and therefore change (COW) only leaf 1. $ chmod 700 /mnt/testdir # Now fsync directory inode 257. # # Since only the first leaf was changed/COWed, we log the inode item of # inode 257 and only the dentries found in the first leaf, all have a # key type of BTRFS_DIR_ITEM_KEY, and no keys of type # BTRFS_DIR_INDEX_KEY, because they sort after the former type and none # exist in the first leaf. # # We also log 3 items that represent ranges for dir items and dir # indexes for which the log is authoritative: # # 1) a key of type BTRFS_DIR_LOG_ITEM_KEY, which indicates the log is # authoritative for all BTRFS_DIR_ITEM_KEY keys that have an offset # in the range [0, 2285968570] (the offset here is th ---truncated---
Impacted products
Vendor Product Version
Linux Linux Version: 5.12
Show details on NVD website


{
  "containers": {
    "adp": [
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2021-47072",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "no"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2024-03-11T16:49:49.252452Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2024-06-04T17:13:49.970Z",
          "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "shortName": "CISA-ADP"
        },
        "title": "CISA ADP Vulnrichment"
      },
      {
        "providerMetadata": {
          "dateUpdated": "2024-08-04T05:24:39.601Z",
          "orgId": "af854a3a-2127-422b-91ae-364da2661108",
          "shortName": "CVE"
        },
        "references": [
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/6d0924c5b742036b4f20a0ffdf2b6cf3f963f5f6"
          },
          {
            "tags": [
              "x_transferred"
            ],
            "url": "https://git.kernel.org/stable/c/54a40fc3a1da21b52dbf19f72fdc27a2ec740760"
          }
        ],
        "title": "CVE Program Container"
      }
    ],
    "cna": {
      "affected": [
        {
          "defaultStatus": "unaffected",
          "product": "Linux",
          "programFiles": [
            "fs/btrfs/tree-log.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "lessThan": "6d0924c5b742036b4f20a0ffdf2b6cf3f963f5f6",
              "status": "affected",
              "version": "64d6b281ba4db044c946158387c74e1149b9487e",
              "versionType": "git"
            },
            {
              "lessThan": "54a40fc3a1da21b52dbf19f72fdc27a2ec740760",
              "status": "affected",
              "version": "64d6b281ba4db044c946158387c74e1149b9487e",
              "versionType": "git"
            }
          ]
        },
        {
          "defaultStatus": "affected",
          "product": "Linux",
          "programFiles": [
            "fs/btrfs/tree-log.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "status": "affected",
              "version": "5.12"
            },
            {
              "lessThan": "5.12",
              "status": "unaffected",
              "version": "0",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "5.12.*",
              "status": "unaffected",
              "version": "5.12.7",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "*",
              "status": "unaffected",
              "version": "5.13",
              "versionType": "original_commit_for_fix"
            }
          ]
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nbtrfs: fix removed dentries still existing after log is synced\n\nWhen we move one inode from one directory to another and both the inode\nand its previous parent directory were logged before, we are not supposed\nto have the dentry for the old parent if we have a power failure after the\nlog is synced. Only the new dentry is supposed to exist.\n\nGenerally this works correctly, however there is a scenario where this is\nnot currently working, because the old parent of the file/directory that\nwas moved is not authoritative for a range that includes the dir index and\ndir item keys of the old dentry. This case is better explained with the\nfollowing example and reproducer:\n\n  # The test requires a very specific layout of keys and items in the\n  # fs/subvolume btree to trigger the bug. So we want to make sure that\n  # on whatever platform we are, we have the same leaf/node size.\n  #\n  # Currently in btrfs the node/leaf size can not be smaller than the page\n  # size (but it can be greater than the page size). So use the largest\n  # supported node/leaf size (64K).\n\n  $ mkfs.btrfs -f -n 65536 /dev/sdc\n  $ mount /dev/sdc /mnt\n\n  # \"testdir\" is inode 257.\n  $ mkdir /mnt/testdir\n  $ chmod 755 /mnt/testdir\n\n  # Create several empty files to have the directory \"testdir\" with its\n  # items spread over several leaves (7 in this case).\n  $ for ((i = 1; i \u003c= 1200; i++)); do\n       echo -n \u003e /mnt/testdir/file$i\n    done\n\n  # Create our test directory \"dira\", inode number 1458, which gets all\n  # its items in leaf 7.\n  #\n  # The BTRFS_DIR_ITEM_KEY item for inode 257 (\"testdir\") that points to\n  # the entry named \"dira\" is in leaf 2, while the BTRFS_DIR_INDEX_KEY\n  # item that points to that entry is in leaf 3.\n  #\n  # For this particular filesystem node size (64K), file count and file\n  # names, we endup with the directory entry items from inode 257 in\n  # leaves 2 and 3, as previously mentioned - what matters for triggering\n  # the bug exercised by this test case is that those items are not placed\n  # in leaf 1, they must be placed in a leaf different from the one\n  # containing the inode item for inode 257.\n  #\n  # The corresponding BTRFS_DIR_ITEM_KEY and BTRFS_DIR_INDEX_KEY items for\n  # the parent inode (257) are the following:\n  #\n  #    item 460 key (257 DIR_ITEM 3724298081) itemoff 48344 itemsize 34\n  #         location key (1458 INODE_ITEM 0) type DIR\n  #         transid 6 data_len 0 name_len 4\n  #         name: dira\n  #\n  # and:\n  #\n  #    item 771 key (257 DIR_INDEX 1202) itemoff 36673 itemsize 34\n  #         location key (1458 INODE_ITEM 0) type DIR\n  #         transid 6 data_len 0 name_len 4\n  #         name: dira\n\n  $ mkdir /mnt/testdir/dira\n\n  # Make sure everything done so far is durably persisted.\n  $ sync\n\n  # Now do a change to inode 257 (\"testdir\") that does not result in\n  # COWing leaves 2 and 3 - the leaves that contain the directory items\n  # pointing to inode 1458 (directory \"dira\").\n  #\n  # Changing permissions, the owner/group, updating or adding a xattr,\n  # etc, will not change (COW) leaves 2 and 3. So for the sake of\n  # simplicity change the permissions of inode 257, which results in\n  # updating its inode item and therefore change (COW) only leaf 1.\n\n  $ chmod 700 /mnt/testdir\n\n  # Now fsync directory inode 257.\n  #\n  # Since only the first leaf was changed/COWed, we log the inode item of\n  # inode 257 and only the dentries found in the first leaf, all have a\n  # key type of BTRFS_DIR_ITEM_KEY, and no keys of type\n  # BTRFS_DIR_INDEX_KEY, because they sort after the former type and none\n  # exist in the first leaf.\n  #\n  # We also log 3 items that represent ranges for dir items and dir\n  # indexes for which the log is authoritative:\n  #\n  # 1) a key of type BTRFS_DIR_LOG_ITEM_KEY, which indicates the log is\n  #    authoritative for all BTRFS_DIR_ITEM_KEY keys that have an offset\n  #    in the range [0, 2285968570] (the offset here is th\n---truncated---"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2024-12-19T07:34:43.837Z",
        "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "shortName": "Linux"
      },
      "references": [
        {
          "url": "https://git.kernel.org/stable/c/6d0924c5b742036b4f20a0ffdf2b6cf3f963f5f6"
        },
        {
          "url": "https://git.kernel.org/stable/c/54a40fc3a1da21b52dbf19f72fdc27a2ec740760"
        }
      ],
      "title": "btrfs: fix removed dentries still existing after log is synced",
      "x_generator": {
        "engine": "bippy-5f407fcff5a0"
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
    "assignerShortName": "Linux",
    "cveId": "CVE-2021-47072",
    "datePublished": "2024-03-01T21:15:10.710Z",
    "dateReserved": "2024-02-29T22:33:44.297Z",
    "dateUpdated": "2024-12-19T07:34:43.837Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.1",
  "vulnerability-lookup:meta": {
    "nvd": "{\"cve\":{\"id\":\"CVE-2021-47072\",\"sourceIdentifier\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\",\"published\":\"2024-03-01T22:15:47.010\",\"lastModified\":\"2024-11-21T06:35:20.567\",\"vulnStatus\":\"Awaiting Analysis\",\"cveTags\":[],\"descriptions\":[{\"lang\":\"en\",\"value\":\"In the Linux kernel, the following vulnerability has been resolved:\\n\\nbtrfs: fix removed dentries still existing after log is synced\\n\\nWhen we move one inode from one directory to another and both the inode\\nand its previous parent directory were logged before, we are not supposed\\nto have the dentry for the old parent if we have a power failure after the\\nlog is synced. Only the new dentry is supposed to exist.\\n\\nGenerally this works correctly, however there is a scenario where this is\\nnot currently working, because the old parent of the file/directory that\\nwas moved is not authoritative for a range that includes the dir index and\\ndir item keys of the old dentry. This case is better explained with the\\nfollowing example and reproducer:\\n\\n  # The test requires a very specific layout of keys and items in the\\n  # fs/subvolume btree to trigger the bug. So we want to make sure that\\n  # on whatever platform we are, we have the same leaf/node size.\\n  #\\n  # Currently in btrfs the node/leaf size can not be smaller than the page\\n  # size (but it can be greater than the page size). So use the largest\\n  # supported node/leaf size (64K).\\n\\n  $ mkfs.btrfs -f -n 65536 /dev/sdc\\n  $ mount /dev/sdc /mnt\\n\\n  # \\\"testdir\\\" is inode 257.\\n  $ mkdir /mnt/testdir\\n  $ chmod 755 /mnt/testdir\\n\\n  # Create several empty files to have the directory \\\"testdir\\\" with its\\n  # items spread over several leaves (7 in this case).\\n  $ for ((i = 1; i \u003c= 1200; i++)); do\\n       echo -n \u003e /mnt/testdir/file$i\\n    done\\n\\n  # Create our test directory \\\"dira\\\", inode number 1458, which gets all\\n  # its items in leaf 7.\\n  #\\n  # The BTRFS_DIR_ITEM_KEY item for inode 257 (\\\"testdir\\\") that points to\\n  # the entry named \\\"dira\\\" is in leaf 2, while the BTRFS_DIR_INDEX_KEY\\n  # item that points to that entry is in leaf 3.\\n  #\\n  # For this particular filesystem node size (64K), file count and file\\n  # names, we endup with the directory entry items from inode 257 in\\n  # leaves 2 and 3, as previously mentioned - what matters for triggering\\n  # the bug exercised by this test case is that those items are not placed\\n  # in leaf 1, they must be placed in a leaf different from the one\\n  # containing the inode item for inode 257.\\n  #\\n  # The corresponding BTRFS_DIR_ITEM_KEY and BTRFS_DIR_INDEX_KEY items for\\n  # the parent inode (257) are the following:\\n  #\\n  #    item 460 key (257 DIR_ITEM 3724298081) itemoff 48344 itemsize 34\\n  #         location key (1458 INODE_ITEM 0) type DIR\\n  #         transid 6 data_len 0 name_len 4\\n  #         name: dira\\n  #\\n  # and:\\n  #\\n  #    item 771 key (257 DIR_INDEX 1202) itemoff 36673 itemsize 34\\n  #         location key (1458 INODE_ITEM 0) type DIR\\n  #         transid 6 data_len 0 name_len 4\\n  #         name: dira\\n\\n  $ mkdir /mnt/testdir/dira\\n\\n  # Make sure everything done so far is durably persisted.\\n  $ sync\\n\\n  # Now do a change to inode 257 (\\\"testdir\\\") that does not result in\\n  # COWing leaves 2 and 3 - the leaves that contain the directory items\\n  # pointing to inode 1458 (directory \\\"dira\\\").\\n  #\\n  # Changing permissions, the owner/group, updating or adding a xattr,\\n  # etc, will not change (COW) leaves 2 and 3. So for the sake of\\n  # simplicity change the permissions of inode 257, which results in\\n  # updating its inode item and therefore change (COW) only leaf 1.\\n\\n  $ chmod 700 /mnt/testdir\\n\\n  # Now fsync directory inode 257.\\n  #\\n  # Since only the first leaf was changed/COWed, we log the inode item of\\n  # inode 257 and only the dentries found in the first leaf, all have a\\n  # key type of BTRFS_DIR_ITEM_KEY, and no keys of type\\n  # BTRFS_DIR_INDEX_KEY, because they sort after the former type and none\\n  # exist in the first leaf.\\n  #\\n  # We also log 3 items that represent ranges for dir items and dir\\n  # indexes for which the log is authoritative:\\n  #\\n  # 1) a key of type BTRFS_DIR_LOG_ITEM_KEY, which indicates the log is\\n  #    authoritative for all BTRFS_DIR_ITEM_KEY keys that have an offset\\n  #    in the range [0, 2285968570] (the offset here is th\\n---truncated---\"},{\"lang\":\"es\",\"value\":\"En el kernel de Linux, se resolvi\u00f3 la siguiente vulnerabilidad: btrfs: corrige las dentries eliminadas que a\u00fan existen despu\u00e9s de sincronizar el registro. Cuando movemos un inodo de un directorio a otro y tanto el inodo como su directorio principal anterior se registraron antes, se supone que no tener la dentry del padre anterior si tenemos un corte de energ\u00eda despu\u00e9s de sincronizar el registro. Se supone que s\u00f3lo existe el nuevo dentry. En general, esto funciona correctamente, sin embargo, hay un escenario en el que esto no funciona actualmente, porque el padre antiguo del archivo/directorio que se movi\u00f3 no tiene autoridad para un rango que incluye el \u00edndice de directorio y las claves de elemento de directorio del dentry anterior. Este caso se explica mejor con el siguiente ejemplo y reproductor: # La prueba requiere un dise\u00f1o muy espec\u00edfico de claves y elementos en el \u00e1rbol # fs/subvolume para activar el error. Por eso queremos asegurarnos de que # en cualquier plataforma en la que estemos, tengamos el mismo tama\u00f1o de hoja/nodo. # # Actualmente en btrfs el tama\u00f1o del nodo/hoja no puede ser menor que el tama\u00f1o de la p\u00e1gina # (pero puede ser mayor que el tama\u00f1o de la p\u00e1gina). Por lo tanto, utilice el mayor tama\u00f1o de nodo/hoja admitido (64K).  $ mkfs.btrfs -f -n 65536 /dev/sdc $ mount /dev/sdc /mnt # \\\"testdir\\\" is inode 257. $ mkdir /mnt/testdir $ chmod 755 /mnt/testdir # Create several empty files to have the directory \\\"testdir\\\" with its # items spread over several leaves (7 in this case). $ for ((i = 1; i \u0026lt;= 1200; i++)); do echo -n \u0026gt; /mnt/testdir/file$i done # Create our test directory \\\"dira\\\", inode number 1458, which gets all # its items in leaf 7. # # The BTRFS_DIR_ITEM_KEY item for inode 257 (\\\"testdir\\\") that points to # the entry named \\\"dira\\\" is in leaf 2, while the BTRFS_DIR_INDEX_KEY # item that points to that entry is in leaf 3. # # For this particular filesystem node size (64K), file count and file # names, we endup with the directory entry items from inode 257 in # leaves 2 and 3, as previously mentioned - what matters for triggering # the bug exercised by this test case is that those items are not placed # in leaf 1, they must be placed in a leaf different from the one # containing the inode item for inode 257. # # The corresponding BTRFS_DIR_ITEM_KEY and BTRFS_DIR_INDEX_KEY items for # the parent inode (257) are the following: # # item 460 key (257 DIR_ITEM 3724298081) itemoff 48344 itemsize 34 # location key (1458 INODE_ITEM 0) type DIR # transid 6 data_len 0 name_len 4 # name: dira # # and: # # item 771 key (257 DIR_INDEX 1202) itemoff 36673 itemsize 34 # location key (1458 INODE_ITEM 0) type DIR # transid 6 data_len 0 name_len 4 # name: dira $ mkdir /mnt/testdir/dira # Make sure everything done so far is durably persisted. $ sync # Now do a change to inode 257 (\\\"testdir\\\") that does not result in # COWing leaves 2 and 3 - the leaves that contain the directory items # pointing to inode 1458 (directory \\\"dira\\\"). # # Changing permissions, the owner/group, updating or adding a xattr, # etc, will not change (COW) leaves 2 and 3. So for the sake of # simplicity change the permissions of inode 257, which results in # updating its inode item and therefore change (COW) only leaf 1. $ chmod 700 /mnt/testdir # Now fsync directory inode 257. # # Since only the first leaf was changed/COWed, we log the inode item of # inode 257 and only the dentries found in the first leaf, all have a # key type of BTRFS_DIR_ITEM_KEY, and no keys of type # BTRFS_DIR_INDEX_KEY, because they sort after the former type and none # exist in the first leaf. # # We also log 3 items that represent ranges for dir items and dir # indexes for which the log is authoritative: # # 1) a key of type BTRFS_DIR_LOG_ITEM_KEY, which indicates the log is # authoritative for all BTRFS_DIR_ITEM_KEY keys that have an offset # in the range [0, 2285968570] (the offset here is th ---truncated--- \"}],\"metrics\":{},\"references\":[{\"url\":\"https://git.kernel.org/stable/c/54a40fc3a1da21b52dbf19f72fdc27a2ec740760\",\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\"},{\"url\":\"https://git.kernel.org/stable/c/6d0924c5b742036b4f20a0ffdf2b6cf3f963f5f6\",\"source\":\"416baaa9-dc9f-4396-8d5f-8c081fb06d67\"},{\"url\":\"https://git.kernel.org/stable/c/54a40fc3a1da21b52dbf19f72fdc27a2ec740760\",\"source\":\"af854a3a-2127-422b-91ae-364da2661108\"},{\"url\":\"https://git.kernel.org/stable/c/6d0924c5b742036b4f20a0ffdf2b6cf3f963f5f6\",\"source\":\"af854a3a-2127-422b-91ae-364da2661108\"}]}}"
  }
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.