Changes in 4.9.285 ocfs2: drop acl cache for directories too usb: gadget: r8a66597: fix a loop in set_feature() usb: musb: tusb6010: uninitialized data in tusb_fifo_write_unaligned() cifs: fix incorrect check for null pointer in header_assemble xen/x86: fix PV trap handling on secondary processors usb-storage: Add quirk for ScanLogic SL11R-IDE older than 2.6c USB: serial: cp210x: add ID for GW Instek GDM-834x Digital Multimeter staging: greybus: uart: fix tty use after free USB: serial: mos7840: remove duplicated 0xac24 device ID USB: serial: option: add Telit LN920 compositions USB: serial: option: remove duplicate USB device ID USB: serial: option: add device id for Foxconn T99W265 mcb: fix error handling in mcb_alloc_bus() serial: mvebu-uart: fix driver's tx_empty callback net: hso: fix muxed tty registration net/mlx4_en: Don't allow aRFS for encapsulated packets scsi: iscsi: Adjust iface sysfs attr detection blktrace: Fix uaf in blk_trace access after removing by sysfs net: stmmac: allow CSR clock of 300MHz m68k: Double cast io functions to unsigned long compiler.h: Introduce absolute_pointer macro net: i825xx: Use absolute_pointer for memcpy from fixed memory location sparc: avoid stringop-overread errors qnx4: avoid stringop-overread errors parisc: Use absolute_pointer() to define PAGE0 arm64: Mark __stack_chk_guard as __ro_after_init alpha: Declare virt_to_phys and virt_to_bus parameter as pointer to volatile net: 6pack: Fix tx timeout and slot time spi: Fix tegra20 build with CONFIG_PM=n arm64: dts: marvell: armada-37xx: Extend PCIe MEM space qnx4: work around gcc false positive warning bug tty: Fix out-of-bound vmalloc access in imageblit cpufreq: schedutil: Use kobject release() method to free sugov_tunables cpufreq: schedutil: Destroy mutex before kobject_put() frees the memory mac80211: fix use-after-free in CCMP/GCMP RX ipvs: check that ip_vs_conn_tab_bits is between 8 and 20 mac80211: limit injected vht mcs/nss in ieee80211_parse_tx_radiotap hwmon: (tmp421) fix rounding for negative values e100: fix length calculation in e100_get_regs_len e100: fix buffer overrun in e100_get_regs ipack: ipoctal: fix stack information leak ipack: ipoctal: fix tty registration race ipack: ipoctal: fix tty-registration error handling ipack: ipoctal: fix missing allocation-failure check ipack: ipoctal: fix module reference leak ext4: fix potential infinite loop in ext4_dx_readdir() net: udp: annotate data race around udp_sk(sk)->corkflag EDAC/synopsys: Fix wrong value type assignment for edac_mode ARM: 9077/1: PLT: Move struct plt_entries definition to header ARM: 9078/1: Add warn suppress parameter to arm_gen_branch_link() ARM: 9079/1: ftrace: Add MODULE_PLTS support ARM: 9098/1: ftrace: MODULE_PLT: Fix build problem without DYNAMIC_FTRACE arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55 HID: betop: fix slab-out-of-bounds Write in betop_probe netfilter: ipset: Fix oversized kvmalloc() calls HID: usbhid: free raw_report buffers in usbhid_stop cred: allow get_cred() and put_cred() to be given NULL. Linux 4.9.285 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I55fa39c89ba10e7092db6001c6feee0d792a401f
117 lines
3.2 KiB
C
117 lines
3.2 KiB
C
/*
|
|
* QNX4 file system, Linux implementation.
|
|
*
|
|
* Version : 0.2.1
|
|
*
|
|
* Using parts of the xiafs filesystem.
|
|
*
|
|
* History :
|
|
*
|
|
* 28-05-1998 by Richard Frowijn : first release.
|
|
* 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support.
|
|
*/
|
|
|
|
#include <linux/buffer_head.h>
|
|
#include "qnx4.h"
|
|
|
|
/*
|
|
* A qnx4 directory entry is an inode entry or link info
|
|
* depending on the status field in the last byte. The
|
|
* first byte is where the name start either way, and a
|
|
* zero means it's empty.
|
|
*
|
|
* Also, due to a bug in gcc, we don't want to use the
|
|
* real (differently sized) name arrays in the inode and
|
|
* link entries, but always the 'de_name[]' one in the
|
|
* fake struct entry.
|
|
*
|
|
* See
|
|
*
|
|
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578#c6
|
|
*
|
|
* for details, but basically gcc will take the size of the
|
|
* 'name' array from one of the used union entries randomly.
|
|
*
|
|
* This use of 'de_name[]' (48 bytes) avoids the false positive
|
|
* warnings that would happen if gcc decides to use 'inode.di_name'
|
|
* (16 bytes) even when the pointer and size were to come from
|
|
* 'link.dl_name' (48 bytes).
|
|
*
|
|
* In all cases the actual name pointer itself is the same, it's
|
|
* only the gcc internal 'what is the size of this field' logic
|
|
* that can get confused.
|
|
*/
|
|
union qnx4_directory_entry {
|
|
struct {
|
|
const char de_name[48];
|
|
u8 de_pad[15];
|
|
u8 de_status;
|
|
};
|
|
struct qnx4_inode_entry inode;
|
|
struct qnx4_link_info link;
|
|
};
|
|
|
|
static int qnx4_readdir(struct file *file, struct dir_context *ctx)
|
|
{
|
|
struct inode *inode = file_inode(file);
|
|
unsigned int offset;
|
|
struct buffer_head *bh;
|
|
unsigned long blknum;
|
|
int ix, ino;
|
|
int size;
|
|
|
|
QNX4DEBUG((KERN_INFO "qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
|
|
QNX4DEBUG((KERN_INFO "pos = %ld\n", (long) ctx->pos));
|
|
|
|
while (ctx->pos < inode->i_size) {
|
|
blknum = qnx4_block_map(inode, ctx->pos >> QNX4_BLOCK_SIZE_BITS);
|
|
bh = sb_bread(inode->i_sb, blknum);
|
|
if (bh == NULL) {
|
|
printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
|
|
return 0;
|
|
}
|
|
ix = (ctx->pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK;
|
|
for (; ix < QNX4_INODES_PER_BLOCK; ix++, ctx->pos += QNX4_DIR_ENTRY_SIZE) {
|
|
union qnx4_directory_entry *de;
|
|
|
|
offset = ix * QNX4_DIR_ENTRY_SIZE;
|
|
de = (union qnx4_directory_entry *) (bh->b_data + offset);
|
|
|
|
if (!de->de_name[0])
|
|
continue;
|
|
if (!(de->de_status & (QNX4_FILE_USED|QNX4_FILE_LINK)))
|
|
continue;
|
|
if (!(de->de_status & QNX4_FILE_LINK)) {
|
|
size = sizeof(de->inode.di_fname);
|
|
ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
|
|
} else {
|
|
size = sizeof(de->link.dl_fname);
|
|
ino = ( le32_to_cpu(de->link.dl_inode_blk) - 1 ) *
|
|
QNX4_INODES_PER_BLOCK +
|
|
de->link.dl_inode_ndx;
|
|
}
|
|
size = strnlen(de->de_name, size);
|
|
QNX4DEBUG((KERN_INFO "qnx4_readdir:%.*s\n", size, name));
|
|
if (!dir_emit(ctx, de->de_name, size, ino, DT_UNKNOWN)) {
|
|
brelse(bh);
|
|
return 0;
|
|
}
|
|
}
|
|
brelse(bh);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const struct file_operations qnx4_dir_operations =
|
|
{
|
|
.llseek = generic_file_llseek,
|
|
.read = generic_read_dir,
|
|
.iterate_shared = qnx4_readdir,
|
|
.fsync = generic_file_fsync,
|
|
};
|
|
|
|
const struct inode_operations qnx4_dir_inode_operations =
|
|
{
|
|
.lookup = qnx4_lookup,
|
|
};
|