2019-05-20 19:08:00 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2010-05-14 20:48:47 +01:00
/*
* Squashfs - a compressed read only filesystem for Linux
*
* Copyright ( c ) 2010
2011-05-26 10:39:56 +01:00
* Phillip Lougher < phillip @ squashfs . org . uk >
2010-05-14 20:48:47 +01:00
*
* xattr_id . c
*/
/*
* This file implements code to map the 32 - bit xattr id stored in the inode
* into the on disk location of the xattr data .
*/
# include <linux/fs.h>
# include <linux/vfs.h>
# include <linux/slab.h>
# include "squashfs_fs.h"
# include "squashfs_fs_sb.h"
# include "squashfs.h"
2010-10-25 00:17:24 +01:00
# include "xattr.h"
2010-05-14 20:48:47 +01:00
/*
* Map xattr id using the xattr id look up table
*/
int squashfs_xattr_lookup ( struct super_block * sb , unsigned int index ,
2010-05-13 16:32:21 -07:00
int * count , unsigned int * size , unsigned long long * xattr )
2010-05-14 20:48:47 +01:00
{
struct squashfs_sb_info * msblk = sb - > s_fs_info ;
int block = SQUASHFS_XATTR_BLOCK ( index ) ;
int offset = SQUASHFS_XATTR_BLOCK_OFFSET ( index ) ;
2021-02-09 13:42:00 -08:00
u64 start_block ;
2010-05-14 20:48:47 +01:00
struct squashfs_xattr_id id ;
int err ;
2021-02-09 13:42:00 -08:00
if ( index > = msblk - > xattr_ids )
return - EINVAL ;
start_block = le64_to_cpu ( msblk - > xattr_id_table [ block ] ) ;
2010-05-14 20:48:47 +01:00
err = squashfs_read_metadata ( sb , & id , & start_block , & offset ,
sizeof ( id ) ) ;
if ( err < 0 )
return err ;
* xattr = le64_to_cpu ( id . xattr ) ;
* size = le32_to_cpu ( id . size ) ;
* count = le32_to_cpu ( id . count ) ;
return 0 ;
}
/*
* Read uncompressed xattr id lookup table indexes from disk into memory
*/
2021-02-09 13:42:00 -08:00
__le64 * squashfs_read_xattr_id_table ( struct super_block * sb , u64 table_start ,
2023-01-27 06:18:42 +00:00
u64 * xattr_table_start , unsigned int * xattr_ids )
2010-05-14 20:48:47 +01:00
{
2021-02-09 13:42:00 -08:00
struct squashfs_sb_info * msblk = sb - > s_fs_info ;
unsigned int len , indexes ;
2011-05-20 02:26:43 +01:00
struct squashfs_xattr_id_table * id_table ;
2021-02-09 13:42:00 -08:00
__le64 * table ;
u64 start , end ;
int n ;
2011-05-20 02:26:43 +01:00
2021-02-09 13:42:00 -08:00
id_table = squashfs_read_table ( sb , table_start , sizeof ( * id_table ) ) ;
2011-05-20 02:26:43 +01:00
if ( IS_ERR ( id_table ) )
return ( __le64 * ) id_table ;
2010-05-14 20:48:47 +01:00
2011-05-20 02:26:43 +01:00
* xattr_table_start = le64_to_cpu ( id_table - > xattr_table_start ) ;
* xattr_ids = le32_to_cpu ( id_table - > xattr_ids ) ;
kfree ( id_table ) ;
2011-05-24 03:20:27 +01:00
/* Sanity check values */
/* there is always at least one xattr id */
2023-02-02 18:07:35 -08:00
if ( * xattr_ids = = 0 )
2011-05-24 03:20:27 +01:00
return ERR_PTR ( - EINVAL ) ;
2021-02-09 13:42:00 -08:00
len = SQUASHFS_XATTR_BLOCK_BYTES ( * xattr_ids ) ;
indexes = SQUASHFS_XATTR_BLOCKS ( * xattr_ids ) ;
/*
* The computed size of the index table ( len bytes ) should exactly
* match the table start and end points
*/
start = table_start + sizeof ( * id_table ) ;
end = msblk - > bytes_used ;
if ( len ! = ( end - start ) )
2011-05-24 03:20:27 +01:00
return ERR_PTR ( - EINVAL ) ;
2021-02-09 13:42:00 -08:00
table = squashfs_read_table ( sb , start , len ) ;
if ( IS_ERR ( table ) )
return table ;
/* table[0], table[1], ... table[indexes - 1] store the locations
* of the compressed xattr id blocks . Each entry should be less than
* the next ( i . e . table [ 0 ] < table [ 1 ] ) , and the difference between them
* should be SQUASHFS_METADATA_SIZE or less . table [ indexes - 1 ]
* should be less than table_start , and again the difference
* shouls be SQUASHFS_METADATA_SIZE or less .
*
* Finally xattr_table_start should be less than table [ 0 ] .
*/
for ( n = 0 ; n < ( indexes - 1 ) ; n + + ) {
start = le64_to_cpu ( table [ n ] ) ;
end = le64_to_cpu ( table [ n + 1 ] ) ;
2021-03-24 21:37:35 -07:00
if ( start > = end | | ( end - start ) >
( SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET ) ) {
2021-02-09 13:42:00 -08:00
kfree ( table ) ;
return ERR_PTR ( - EINVAL ) ;
}
}
start = le64_to_cpu ( table [ indexes - 1 ] ) ;
2021-03-24 21:37:35 -07:00
if ( start > = table_start | | ( table_start - start ) >
( SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET ) ) {
2021-02-09 13:42:00 -08:00
kfree ( table ) ;
return ERR_PTR ( - EINVAL ) ;
}
2010-05-14 20:48:47 +01:00
2021-02-09 13:42:00 -08:00
if ( * xattr_table_start > = le64_to_cpu ( table [ 0 ] ) ) {
kfree ( table ) ;
return ERR_PTR ( - EINVAL ) ;
}
2010-05-14 20:48:47 +01:00
2021-02-09 13:42:00 -08:00
return table ;
2010-05-14 20:48:47 +01:00
}