Merge 4.19.319 into android-4.19-stable

Changes in 4.19.319
	gcc-plugins: Rename last_stmt() for GCC 14+
	scsi: qedf: Set qed_slowpath_params to zero before use
	ACPI: EC: Abort address space access upon error
	ACPI: EC: Avoid returning AE_OK on errors in address space handler
	wifi: mac80211: mesh: init nonpeer_pm to active by default in mesh sdata
	wifi: mac80211: fix UBSAN noise in ieee80211_prep_hw_scan()
	Input: silead - Always support 10 fingers
	ila: block BH in ila_output()
	kconfig: gconf: give a proper initial state to the Save button
	kconfig: remove wrong expr_trans_bool()
	fs/file: fix the check in find_next_fd()
	mei: demote client disconnect warning on suspend to debug
	wifi: cfg80211: wext: add extra SIOCSIWSCAN data check
	Input: elantech - fix touchpad state on resume for Lenovo N24
	bytcr_rt5640 : inverse jack detect for Archos 101 cesium
	can: kvaser_usb: fix return value for hif_usb_send_regout
	s390/sclp: Fix sclp_init() cleanup on failure
	ALSA: dmaengine_pcm: terminate dmaengine before synchronize
	net: usb: qmi_wwan: add Telit FN912 compositions
	net: mac802154: Fix racy device stats updates by DEV_STATS_INC() and DEV_STATS_ADD()
	Bluetooth: hci_core: cancel all works upon hci_unregister_dev()
	fs: better handle deep ancestor chains in is_subdir()
	spi: imx: Don't expect DMA for i.MX{25,35,50,51,53} cspi devices
	selftests/vDSO: fix clang build errors and warnings
	hfsplus: fix uninit-value in copy_name
	filelock: Remove locks reliably when fcntl/close race is detected
	ARM: 9324/1: fix get_user() broken with veneer
	ACPI: processor_idle: Fix invalid comparison with insertion sort for latency
	net: relax socket state check at accept time.
	ocfs2: add bounds checking to ocfs2_check_dir_entry()
	jfs: don't walk off the end of ealist
	filelock: Fix fcntl/close race recovery compat path
	Linux 4.19.319

Change-Id: Ic95938f445f72bf8c4604f405929da254471d15e
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-07-31 16:26:38 +00:00
34 changed files with 232 additions and 159 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
VERSION = 4 VERSION = 4
PATCHLEVEL = 19 PATCHLEVEL = 19
SUBLEVEL = 318 SUBLEVEL = 319
EXTRAVERSION = EXTRAVERSION =
NAME = "People's Front" NAME = "People's Front"

View File

@@ -145,16 +145,6 @@ extern int __get_user_64t_1(void *);
extern int __get_user_64t_2(void *); extern int __get_user_64t_2(void *);
extern int __get_user_64t_4(void *); extern int __get_user_64t_4(void *);
#define __GUP_CLOBBER_1 "lr", "cc"
#ifdef CONFIG_CPU_USE_DOMAINS
#define __GUP_CLOBBER_2 "ip", "lr", "cc"
#else
#define __GUP_CLOBBER_2 "lr", "cc"
#endif
#define __GUP_CLOBBER_4 "lr", "cc"
#define __GUP_CLOBBER_32t_8 "lr", "cc"
#define __GUP_CLOBBER_8 "lr", "cc"
#define __get_user_x(__r2, __p, __e, __l, __s) \ #define __get_user_x(__r2, __p, __e, __l, __s) \
__asm__ __volatile__ ( \ __asm__ __volatile__ ( \
__asmeq("%0", "r0") __asmeq("%1", "r2") \ __asmeq("%0", "r0") __asmeq("%1", "r2") \
@@ -162,7 +152,7 @@ extern int __get_user_64t_4(void *);
"bl __get_user_" #__s \ "bl __get_user_" #__s \
: "=&r" (__e), "=r" (__r2) \ : "=&r" (__e), "=r" (__r2) \
: "0" (__p), "r" (__l) \ : "0" (__p), "r" (__l) \
: __GUP_CLOBBER_##__s) : "ip", "lr", "cc")
/* narrowing a double-word get into a single 32bit word register: */ /* narrowing a double-word get into a single 32bit word register: */
#ifdef __ARMEB__ #ifdef __ARMEB__
@@ -184,7 +174,7 @@ extern int __get_user_64t_4(void *);
"bl __get_user_64t_" #__s \ "bl __get_user_64t_" #__s \
: "=&r" (__e), "=r" (__r2) \ : "=&r" (__e), "=r" (__r2) \
: "0" (__p), "r" (__l) \ : "0" (__p), "r" (__l) \
: __GUP_CLOBBER_##__s) : "ip", "lr", "cc")
#else #else
#define __get_user_x_64t __get_user_x #define __get_user_x_64t __get_user_x
#endif #endif

View File

@@ -1330,10 +1330,13 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
if (ec->busy_polling || bits > 8) if (ec->busy_polling || bits > 8)
acpi_ec_burst_enable(ec); acpi_ec_burst_enable(ec);
for (i = 0; i < bytes; ++i, ++address, ++value) for (i = 0; i < bytes; ++i, ++address, ++value) {
result = (function == ACPI_READ) ? result = (function == ACPI_READ) ?
acpi_ec_read(ec, address, value) : acpi_ec_read(ec, address, value) :
acpi_ec_write(ec, address, *value); acpi_ec_write(ec, address, *value);
if (result < 0)
break;
}
if (ec->busy_polling || bits > 8) if (ec->busy_polling || bits > 8)
acpi_ec_burst_disable(ec); acpi_ec_burst_disable(ec);
@@ -1345,8 +1348,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
return AE_NOT_FOUND; return AE_NOT_FOUND;
case -ETIME: case -ETIME:
return AE_TIME; return AE_TIME;
default: case 0:
return AE_OK; return AE_OK;
default:
return AE_ERROR;
} }
} }

View File

@@ -29,7 +29,6 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/sched.h> /* need_resched() */ #include <linux/sched.h> /* need_resched() */
#include <linux/sort.h>
#include <linux/tick.h> #include <linux/tick.h>
#include <linux/cpuidle.h> #include <linux/cpuidle.h>
#include <linux/cpu.h> #include <linux/cpu.h>
@@ -545,28 +544,24 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
return; return;
} }
static int acpi_cst_latency_cmp(const void *a, const void *b) static void acpi_cst_latency_sort(struct acpi_processor_cx *states, size_t length)
{ {
const struct acpi_processor_cx *x = a, *y = b; int i, j, k;
if (!(x->valid && y->valid)) for (i = 1; i < length; i++) {
return 0; if (!states[i].valid)
if (x->latency > y->latency) continue;
return 1;
if (x->latency < y->latency)
return -1;
return 0;
}
static void acpi_cst_latency_swap(void *a, void *b, int n)
{
struct acpi_processor_cx *x = a, *y = b;
u32 tmp;
if (!(x->valid && y->valid)) for (j = i - 1, k = i; j >= 0; j--) {
return; if (!states[j].valid)
tmp = x->latency; continue;
x->latency = y->latency;
y->latency = tmp; if (states[j].latency > states[k].latency)
swap(states[j].latency, states[k].latency);
k = j;
}
}
} }
static int acpi_processor_power_verify(struct acpi_processor *pr) static int acpi_processor_power_verify(struct acpi_processor *pr)
@@ -611,10 +606,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
if (buggy_latency) { if (buggy_latency) {
pr_notice("FW issue: working around C-state latencies out of order\n"); pr_notice("FW issue: working around C-state latencies out of order\n");
sort(&pr->power.states[1], max_cstate, acpi_cst_latency_sort(&pr->power.states[1], max_cstate);
sizeof(struct acpi_processor_cx),
acpi_cst_latency_cmp,
acpi_cst_latency_swap);
} }
lapic_timer_propagate_broadcast(pr); lapic_timer_propagate_broadcast(pr);

View File

@@ -1527,16 +1527,47 @@ static void elantech_disconnect(struct psmouse *psmouse)
psmouse->private = NULL; psmouse->private = NULL;
} }
/*
* Some hw_version 4 models fail to properly activate absolute mode on
* resume without going through disable/enable cycle.
*/
static const struct dmi_system_id elantech_needs_reenable[] = {
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
{
/* Lenovo N24 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "81AF"),
},
},
#endif
{ }
};
/* /*
* Put the touchpad back into absolute mode when reconnecting * Put the touchpad back into absolute mode when reconnecting
*/ */
static int elantech_reconnect(struct psmouse *psmouse) static int elantech_reconnect(struct psmouse *psmouse)
{ {
int err;
psmouse_reset(psmouse); psmouse_reset(psmouse);
if (elantech_detect(psmouse, 0)) if (elantech_detect(psmouse, 0))
return -1; return -1;
if (dmi_check_system(elantech_needs_reenable)) {
err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE);
if (err)
psmouse_warn(psmouse, "failed to deactivate mouse on %s: %d\n",
psmouse->ps2dev.serio->phys, err);
err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
if (err)
psmouse_warn(psmouse, "failed to reactivate mouse on %s: %d\n",
psmouse->ps2dev.serio->phys, err);
}
if (elantech_set_absolute_mode(psmouse)) { if (elantech_set_absolute_mode(psmouse)) {
psmouse_err(psmouse, psmouse_err(psmouse,
"failed to put touchpad back into absolute mode.\n"); "failed to put touchpad back into absolute mode.\n");

View File

@@ -78,7 +78,6 @@ struct silead_ts_data {
struct regulator_bulk_data regulators[2]; struct regulator_bulk_data regulators[2];
char fw_name[64]; char fw_name[64];
struct touchscreen_properties prop; struct touchscreen_properties prop;
u32 max_fingers;
u32 chip_id; u32 chip_id;
struct input_mt_pos pos[SILEAD_MAX_FINGERS]; struct input_mt_pos pos[SILEAD_MAX_FINGERS];
int slots[SILEAD_MAX_FINGERS]; int slots[SILEAD_MAX_FINGERS];
@@ -106,7 +105,7 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data)
input_set_abs_params(data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0); input_set_abs_params(data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
touchscreen_parse_properties(data->input, true, &data->prop); touchscreen_parse_properties(data->input, true, &data->prop);
input_mt_init_slots(data->input, data->max_fingers, input_mt_init_slots(data->input, SILEAD_MAX_FINGERS,
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
INPUT_MT_TRACK); INPUT_MT_TRACK);
@@ -153,10 +152,10 @@ static void silead_ts_read_data(struct i2c_client *client)
return; return;
} }
if (buf[0] > data->max_fingers) { if (buf[0] > SILEAD_MAX_FINGERS) {
dev_warn(dev, "More touches reported then supported %d > %d\n", dev_warn(dev, "More touches reported then supported %d > %d\n",
buf[0], data->max_fingers); buf[0], SILEAD_MAX_FINGERS);
buf[0] = data->max_fingers; buf[0] = SILEAD_MAX_FINGERS;
} }
touch_nr = 0; touch_nr = 0;
@@ -208,7 +207,6 @@ static void silead_ts_read_data(struct i2c_client *client)
static int silead_ts_init(struct i2c_client *client) static int silead_ts_init(struct i2c_client *client)
{ {
struct silead_ts_data *data = i2c_get_clientdata(client);
int error; int error;
error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET, error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET,
@@ -218,7 +216,7 @@ static int silead_ts_init(struct i2c_client *client)
usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX); usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR, error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR,
data->max_fingers); SILEAD_MAX_FINGERS);
if (error) if (error)
goto i2c_write_err; goto i2c_write_err;
usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX); usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
@@ -445,13 +443,6 @@ static void silead_ts_read_props(struct i2c_client *client)
const char *str; const char *str;
int error; int error;
error = device_property_read_u32(dev, "silead,max-fingers",
&data->max_fingers);
if (error) {
dev_dbg(dev, "Max fingers read error %d\n", error);
data->max_fingers = 5; /* Most devices handle up-to 5 fingers */
}
error = device_property_read_string(dev, "firmware-name", &str); error = device_property_read_string(dev, "firmware-name", &str);
if (!error) if (!error)
snprintf(data->fw_name, sizeof(data->fw_name), snprintf(data->fw_name, sizeof(data->fw_name),

View File

@@ -271,7 +271,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
} }
if (!mei_cl_is_connected(cl)) { if (!mei_cl_is_connected(cl)) {
cl_err(dev, cl, "is not connected"); cl_dbg(dev, cl, "is not connected");
rets = -ENODEV; rets = -ENODEV;
goto out; goto out;
} }

View File

@@ -266,7 +266,7 @@ int kvaser_usb_send_cmd_async(struct kvaser_usb_net_priv *priv, void *cmd,
} }
usb_free_urb(urb); usb_free_urb(urb);
return 0; return err;
} }
int kvaser_usb_can_rx_over_error(struct net_device *netdev) int kvaser_usb_can_rx_over_error(struct net_device *netdev)

View File

@@ -1337,6 +1337,8 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1260, 2)}, /* Telit LE910Cx */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1260, 2)}, /* Telit LE910Cx */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1261, 2)}, /* Telit LE910Cx */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1261, 2)}, /* Telit LE910Cx */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x1900, 1)}, /* Telit LN940 series */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1900, 1)}, /* Telit LN940 series */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x3000, 0)}, /* Telit FN912 series */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x3001, 0)}, /* Telit FN912 series */
{QMI_FIXED_INTF(0x1c9e, 0x9801, 3)}, /* Telewell TW-3G HSPA+ */ {QMI_FIXED_INTF(0x1c9e, 0x9801, 3)}, /* Telewell TW-3G HSPA+ */
{QMI_FIXED_INTF(0x1c9e, 0x9803, 4)}, /* Telewell TW-3G HSPA+ */ {QMI_FIXED_INTF(0x1c9e, 0x9803, 4)}, /* Telewell TW-3G HSPA+ */
{QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)}, /* XS Stick W100-2 from 4G Systems */ {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)}, /* XS Stick W100-2 from 4G Systems */

View File

@@ -1206,6 +1206,7 @@ sclp_init(void)
fail_unregister_reboot_notifier: fail_unregister_reboot_notifier:
unregister_reboot_notifier(&sclp_reboot_notifier); unregister_reboot_notifier(&sclp_reboot_notifier);
fail_init_state_uninitialized: fail_init_state_uninitialized:
list_del(&sclp_state_change_event.list);
sclp_init_state = sclp_init_state_uninitialized; sclp_init_state = sclp_init_state_uninitialized;
fail_unlock: fail_unlock:
spin_unlock_irqrestore(&sclp_lock, flags); spin_unlock_irqrestore(&sclp_lock, flags);

View File

@@ -3101,6 +3101,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
} }
/* Start the Slowpath-process */ /* Start the Slowpath-process */
memset(&slowpath_params, 0, sizeof(struct qed_slowpath_params));
slowpath_params.int_mode = QED_INT_MODE_MSIX; slowpath_params.int_mode = QED_INT_MODE_MSIX;
slowpath_params.drv_major = QEDF_DRIVER_MAJOR_VER; slowpath_params.drv_major = QEDF_DRIVER_MAJOR_VER;
slowpath_params.drv_minor = QEDF_DRIVER_MINOR_VER; slowpath_params.drv_minor = QEDF_DRIVER_MINOR_VER;

View File

@@ -968,7 +968,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = {
.rx_available = mx31_rx_available, .rx_available = mx31_rx_available,
.reset = mx31_reset, .reset = mx31_reset,
.fifo_size = 8, .fifo_size = 8,
.has_dmamode = true, .has_dmamode = false,
.dynamic_burst = false, .dynamic_burst = false,
.has_slavemode = false, .has_slavemode = false,
.devtype = IMX35_CSPI, .devtype = IMX35_CSPI,

View File

@@ -2970,28 +2970,25 @@ EXPORT_SYMBOL(d_splice_alias);
bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry) bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
{ {
bool result; bool subdir;
unsigned seq; unsigned seq;
if (new_dentry == old_dentry) if (new_dentry == old_dentry)
return true; return true;
do { /* Access d_parent under rcu as d_move() may change it. */
/* for restarting inner loop in case of seq retry */ rcu_read_lock();
seq = read_seqbegin(&rename_lock); seq = read_seqbegin(&rename_lock);
/* subdir = d_ancestor(old_dentry, new_dentry);
* Need rcu_readlock to protect against the d_parent trashing /* Try lockless once... */
* due to d_move if (read_seqretry(&rename_lock, seq)) {
*/ /* ...else acquire lock for progress even on deep chains. */
rcu_read_lock(); read_seqlock_excl(&rename_lock);
if (d_ancestor(old_dentry, new_dentry)) subdir = d_ancestor(old_dentry, new_dentry);
result = true; read_sequnlock_excl(&rename_lock);
else }
result = false; rcu_read_unlock();
rcu_read_unlock(); return subdir;
} while (read_seqretry(&rename_lock, seq));
return result;
} }
EXPORT_SYMBOL(is_subdir); EXPORT_SYMBOL(is_subdir);

View File

@@ -462,12 +462,12 @@ struct files_struct init_files = {
static unsigned int find_next_fd(struct fdtable *fdt, unsigned int start) static unsigned int find_next_fd(struct fdtable *fdt, unsigned int start)
{ {
unsigned int maxfd = fdt->max_fds; unsigned int maxfd = fdt->max_fds; /* always multiple of BITS_PER_LONG */
unsigned int maxbit = maxfd / BITS_PER_LONG; unsigned int maxbit = maxfd / BITS_PER_LONG;
unsigned int bitbit = start / BITS_PER_LONG; unsigned int bitbit = start / BITS_PER_LONG;
bitbit = find_next_zero_bit(fdt->full_fds_bits, maxbit, bitbit) * BITS_PER_LONG; bitbit = find_next_zero_bit(fdt->full_fds_bits, maxbit, bitbit) * BITS_PER_LONG;
if (bitbit > maxfd) if (bitbit >= maxfd)
return maxfd; return maxfd;
if (bitbit > start) if (bitbit > start)
start = bitbit; start = bitbit;

View File

@@ -700,7 +700,7 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size)
return err; return err;
} }
strbuf = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN + strbuf = kzalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_ATTR_MAX_STRLEN +
XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL); XATTR_MAC_OSX_PREFIX_LEN + 1, GFP_KERNEL);
if (!strbuf) { if (!strbuf) {
res = -ENOMEM; res = -ENOMEM;

View File

@@ -810,7 +810,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
size_t buf_size) size_t buf_size)
{ {
struct jfs_ea_list *ealist; struct jfs_ea_list *ealist;
struct jfs_ea *ea; struct jfs_ea *ea, *ealist_end;
struct ea_buffer ea_buf; struct ea_buffer ea_buf;
int xattr_size; int xattr_size;
ssize_t size; ssize_t size;
@@ -830,9 +830,16 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
goto not_found; goto not_found;
ealist = (struct jfs_ea_list *) ea_buf.xattr; ealist = (struct jfs_ea_list *) ea_buf.xattr;
ealist_end = END_EALIST(ealist);
/* Find the named attribute */ /* Find the named attribute */
for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) for (ea = FIRST_EA(ealist); ea < ealist_end; ea = NEXT_EA(ea)) {
if (unlikely(ea + 1 > ealist_end) ||
unlikely(NEXT_EA(ea) > ealist_end)) {
size = -EUCLEAN;
goto release;
}
if ((namelen == ea->namelen) && if ((namelen == ea->namelen) &&
memcmp(name, ea->name, namelen) == 0) { memcmp(name, ea->name, namelen) == 0) {
/* Found it */ /* Found it */
@@ -847,6 +854,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
memcpy(data, value, size); memcpy(data, value, size);
goto release; goto release;
} }
}
not_found: not_found:
size = -ENODATA; size = -ENODATA;
release: release:
@@ -874,7 +882,7 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
ssize_t size = 0; ssize_t size = 0;
int xattr_size; int xattr_size;
struct jfs_ea_list *ealist; struct jfs_ea_list *ealist;
struct jfs_ea *ea; struct jfs_ea *ea, *ealist_end;
struct ea_buffer ea_buf; struct ea_buffer ea_buf;
down_read(&JFS_IP(inode)->xattr_sem); down_read(&JFS_IP(inode)->xattr_sem);
@@ -889,9 +897,16 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
goto release; goto release;
ealist = (struct jfs_ea_list *) ea_buf.xattr; ealist = (struct jfs_ea_list *) ea_buf.xattr;
ealist_end = END_EALIST(ealist);
/* compute required size of list */ /* compute required size of list */
for (ea = FIRST_EA(ealist); ea < END_EALIST(ealist); ea = NEXT_EA(ea)) { for (ea = FIRST_EA(ealist); ea < ealist_end; ea = NEXT_EA(ea)) {
if (unlikely(ea + 1 > ealist_end) ||
unlikely(NEXT_EA(ea) > ealist_end)) {
size = -EUCLEAN;
goto release;
}
if (can_list(ea)) if (can_list(ea))
size += name_size(ea) + 1; size += name_size(ea) + 1;
} }

View File

@@ -2297,8 +2297,9 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
error = do_lock_file_wait(filp, cmd, file_lock); error = do_lock_file_wait(filp, cmd, file_lock);
/* /*
* Attempt to detect a close/fcntl race and recover by releasing the * Detect close/fcntl races and recover by zapping all POSIX locks
* lock that was just acquired. There is no need to do that when we're * associated with this file and our files_struct, just like on
* filp_flush(). There is no need to do that when we're
* unlocking though, or for OFD locks. * unlocking though, or for OFD locks.
*/ */
if (!error && file_lock->fl_type != F_UNLCK && if (!error && file_lock->fl_type != F_UNLCK &&
@@ -2312,9 +2313,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
f = fcheck(fd); f = fcheck(fd);
spin_unlock(&current->files->file_lock); spin_unlock(&current->files->file_lock);
if (f != filp) { if (f != filp) {
file_lock->fl_type = F_UNLCK; locks_remove_posix(filp, &current->files);
error = do_lock_file_wait(filp, cmd, file_lock);
WARN_ON_ONCE(error);
error = -EBADF; error = -EBADF;
} }
} }
@@ -2428,8 +2427,9 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
error = do_lock_file_wait(filp, cmd, file_lock); error = do_lock_file_wait(filp, cmd, file_lock);
/* /*
* Attempt to detect a close/fcntl race and recover by releasing the * Detect close/fcntl races and recover by zapping all POSIX locks
* lock that was just acquired. There is no need to do that when we're * associated with this file and our files_struct, just like on
* filp_flush(). There is no need to do that when we're
* unlocking though, or for OFD locks. * unlocking though, or for OFD locks.
*/ */
if (!error && file_lock->fl_type != F_UNLCK && if (!error && file_lock->fl_type != F_UNLCK &&
@@ -2443,9 +2443,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
f = fcheck(fd); f = fcheck(fd);
spin_unlock(&current->files->file_lock); spin_unlock(&current->files->file_lock);
if (f != filp) { if (f != filp) {
file_lock->fl_type = F_UNLCK; locks_remove_posix(filp, &current->files);
error = do_lock_file_wait(filp, cmd, file_lock);
WARN_ON_ONCE(error);
error = -EBADF; error = -EBADF;
} }
} }

View File

@@ -314,13 +314,16 @@ static void ocfs2_dx_dir_name_hash(struct inode *dir, const char *name, int len,
* bh passed here can be an inode block or a dir data block, depending * bh passed here can be an inode block or a dir data block, depending
* on the inode inline data flag. * on the inode inline data flag.
*/ */
static int ocfs2_check_dir_entry(struct inode * dir, static int ocfs2_check_dir_entry(struct inode *dir,
struct ocfs2_dir_entry * de, struct ocfs2_dir_entry *de,
struct buffer_head * bh, struct buffer_head *bh,
char *buf,
unsigned int size,
unsigned long offset) unsigned long offset)
{ {
const char *error_msg = NULL; const char *error_msg = NULL;
const int rlen = le16_to_cpu(de->rec_len); const int rlen = le16_to_cpu(de->rec_len);
const unsigned long next_offset = ((char *) de - buf) + rlen;
if (unlikely(rlen < OCFS2_DIR_REC_LEN(1))) if (unlikely(rlen < OCFS2_DIR_REC_LEN(1)))
error_msg = "rec_len is smaller than minimal"; error_msg = "rec_len is smaller than minimal";
@@ -328,9 +331,11 @@ static int ocfs2_check_dir_entry(struct inode * dir,
error_msg = "rec_len % 4 != 0"; error_msg = "rec_len % 4 != 0";
else if (unlikely(rlen < OCFS2_DIR_REC_LEN(de->name_len))) else if (unlikely(rlen < OCFS2_DIR_REC_LEN(de->name_len)))
error_msg = "rec_len is too small for name_len"; error_msg = "rec_len is too small for name_len";
else if (unlikely( else if (unlikely(next_offset > size))
((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)) error_msg = "directory entry overrun";
error_msg = "directory entry across blocks"; else if (unlikely(next_offset > size - OCFS2_DIR_REC_LEN(1)) &&
next_offset != size)
error_msg = "directory entry too close to end";
if (unlikely(error_msg != NULL)) if (unlikely(error_msg != NULL))
mlog(ML_ERROR, "bad entry in directory #%llu: %s - " mlog(ML_ERROR, "bad entry in directory #%llu: %s - "
@@ -372,16 +377,17 @@ static inline int ocfs2_search_dirblock(struct buffer_head *bh,
de_buf = first_de; de_buf = first_de;
dlimit = de_buf + bytes; dlimit = de_buf + bytes;
while (de_buf < dlimit) { while (de_buf < dlimit - OCFS2_DIR_MEMBER_LEN) {
/* this code is executed quadratically often */ /* this code is executed quadratically often */
/* do minimal checking `by hand' */ /* do minimal checking `by hand' */
de = (struct ocfs2_dir_entry *) de_buf; de = (struct ocfs2_dir_entry *) de_buf;
if (de_buf + namelen <= dlimit && if (de->name + namelen <= dlimit &&
ocfs2_match(namelen, name, de)) { ocfs2_match(namelen, name, de)) {
/* found a match - just to be sure, do a full check */ /* found a match - just to be sure, do a full check */
if (!ocfs2_check_dir_entry(dir, de, bh, offset)) { if (!ocfs2_check_dir_entry(dir, de, bh, first_de,
bytes, offset)) {
ret = -1; ret = -1;
goto bail; goto bail;
} }
@@ -1158,7 +1164,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
pde = NULL; pde = NULL;
de = (struct ocfs2_dir_entry *) first_de; de = (struct ocfs2_dir_entry *) first_de;
while (i < bytes) { while (i < bytes) {
if (!ocfs2_check_dir_entry(dir, de, bh, i)) { if (!ocfs2_check_dir_entry(dir, de, bh, first_de, bytes, i)) {
status = -EIO; status = -EIO;
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
@@ -1658,7 +1664,8 @@ int __ocfs2_add_entry(handle_t *handle,
/* These checks should've already been passed by the /* These checks should've already been passed by the
* prepare function, but I guess we can leave them * prepare function, but I guess we can leave them
* here anyway. */ * here anyway. */
if (!ocfs2_check_dir_entry(dir, de, insert_bh, offset)) { if (!ocfs2_check_dir_entry(dir, de, insert_bh, data_start,
size, offset)) {
retval = -ENOENT; retval = -ENOENT;
goto bail; goto bail;
} }
@@ -1796,7 +1803,8 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode,
} }
de = (struct ocfs2_dir_entry *) (data->id_data + ctx->pos); de = (struct ocfs2_dir_entry *) (data->id_data + ctx->pos);
if (!ocfs2_check_dir_entry(inode, de, di_bh, ctx->pos)) { if (!ocfs2_check_dir_entry(inode, de, di_bh, (char *)data->id_data,
i_size_read(inode), ctx->pos)) {
/* On error, skip the f_pos to the end. */ /* On error, skip the f_pos to the end. */
ctx->pos = i_size_read(inode); ctx->pos = i_size_read(inode);
break; break;
@@ -1893,7 +1901,8 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
while (ctx->pos < i_size_read(inode) while (ctx->pos < i_size_read(inode)
&& offset < sb->s_blocksize) { && offset < sb->s_blocksize) {
de = (struct ocfs2_dir_entry *) (bh->b_data + offset); de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { if (!ocfs2_check_dir_entry(inode, de, bh, bh->b_data,
sb->s_blocksize, offset)) {
/* On error, skip the f_pos to the /* On error, skip the f_pos to the
next block. */ next block. */
ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1; ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1;
@@ -3369,7 +3378,7 @@ static int ocfs2_find_dir_space_id(struct inode *dir, struct buffer_head *di_bh,
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
struct ocfs2_dir_entry *de, *last_de = NULL; struct ocfs2_dir_entry *de, *last_de = NULL;
char *de_buf, *limit; char *first_de, *de_buf, *limit;
unsigned long offset = 0; unsigned long offset = 0;
unsigned int rec_len, new_rec_len, free_space = dir->i_sb->s_blocksize; unsigned int rec_len, new_rec_len, free_space = dir->i_sb->s_blocksize;
@@ -3382,14 +3391,16 @@ static int ocfs2_find_dir_space_id(struct inode *dir, struct buffer_head *di_bh,
else else
free_space = dir->i_sb->s_blocksize - i_size_read(dir); free_space = dir->i_sb->s_blocksize - i_size_read(dir);
de_buf = di->id2.i_data.id_data; first_de = di->id2.i_data.id_data;
de_buf = first_de;
limit = de_buf + i_size_read(dir); limit = de_buf + i_size_read(dir);
rec_len = OCFS2_DIR_REC_LEN(namelen); rec_len = OCFS2_DIR_REC_LEN(namelen);
while (de_buf < limit) { while (de_buf < limit) {
de = (struct ocfs2_dir_entry *)de_buf; de = (struct ocfs2_dir_entry *)de_buf;
if (!ocfs2_check_dir_entry(dir, de, di_bh, offset)) { if (!ocfs2_check_dir_entry(dir, de, di_bh, first_de,
i_size_read(dir), offset)) {
ret = -ENOENT; ret = -ENOENT;
goto out; goto out;
} }
@@ -3471,7 +3482,8 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
/* move to next block */ /* move to next block */
de = (struct ocfs2_dir_entry *) bh->b_data; de = (struct ocfs2_dir_entry *) bh->b_data;
} }
if (!ocfs2_check_dir_entry(dir, de, bh, offset)) { if (!ocfs2_check_dir_entry(dir, de, bh, bh->b_data, blocksize,
offset)) {
status = -ENOENT; status = -ENOENT;
goto bail; goto bail;
} }

View File

@@ -3286,7 +3286,11 @@ void hci_unregister_dev(struct hci_dev *hdev)
list_del(&hdev->list); list_del(&hdev->list);
write_unlock(&hci_dev_list_lock); write_unlock(&hci_dev_list_lock);
cancel_work_sync(&hdev->rx_work);
cancel_work_sync(&hdev->cmd_work);
cancel_work_sync(&hdev->tx_work);
cancel_work_sync(&hdev->power_on); cancel_work_sync(&hdev->power_on);
cancel_work_sync(&hdev->error_reset);
hci_dev_do_close(hdev); hci_dev_do_close(hdev);

View File

@@ -747,7 +747,9 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags,
sock_rps_record_flow(sk2); sock_rps_record_flow(sk2);
WARN_ON(!((1 << sk2->sk_state) & WARN_ON(!((1 << sk2->sk_state) &
(TCPF_ESTABLISHED | TCPF_SYN_RECV | (TCPF_ESTABLISHED | TCPF_SYN_RECV |
TCPF_CLOSE_WAIT | TCPF_CLOSE))); TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 |
TCPF_CLOSING | TCPF_CLOSE_WAIT |
TCPF_CLOSE)));
sock_graft(sk2, newsock); sock_graft(sk2, newsock);

View File

@@ -58,7 +58,9 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
return orig_dst->lwtstate->orig_output(net, sk, skb); return orig_dst->lwtstate->orig_output(net, sk, skb);
} }
local_bh_disable();
dst = dst_cache_get(&ilwt->dst_cache); dst = dst_cache_get(&ilwt->dst_cache);
local_bh_enable();
if (unlikely(!dst)) { if (unlikely(!dst)) {
struct ipv6hdr *ip6h = ipv6_hdr(skb); struct ipv6hdr *ip6h = ipv6_hdr(skb);
struct flowi6 fl6; struct flowi6 fl6;
@@ -86,8 +88,11 @@ static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
goto drop; goto drop;
} }
if (ilwt->connected) if (ilwt->connected) {
local_bh_disable();
dst_cache_set_ip6(&ilwt->dst_cache, dst, &fl6.saddr); dst_cache_set_ip6(&ilwt->dst_cache, dst, &fl6.saddr);
local_bh_enable();
}
} }
skb_dst_set(skb, dst); skb_dst_set(skb, dst);

View File

@@ -1454,6 +1454,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
ifmsh->last_preq = jiffies; ifmsh->last_preq = jiffies;
ifmsh->next_perr = jiffies; ifmsh->next_perr = jiffies;
ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
ifmsh->nonpeer_pm = NL80211_MESH_POWER_ACTIVE;
/* Allocate all mesh structures when creating the first mesh interface. */ /* Allocate all mesh structures when creating the first mesh interface. */
if (!mesh_allocated) if (!mesh_allocated)
ieee80211s_init(); ieee80211s_init();

View File

@@ -652,15 +652,21 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
local->hw_scan_ies_bufsize *= n_bands; local->hw_scan_ies_bufsize *= n_bands;
} }
local->hw_scan_req = kmalloc( local->hw_scan_req = kmalloc(struct_size(local->hw_scan_req,
sizeof(*local->hw_scan_req) + req.channels,
req->n_channels * sizeof(req->channels[0]) + req->n_channels) +
local->hw_scan_ies_bufsize, GFP_KERNEL); local->hw_scan_ies_bufsize,
GFP_KERNEL);
if (!local->hw_scan_req) if (!local->hw_scan_req)
return -ENOMEM; return -ENOMEM;
local->hw_scan_req->req.ssids = req->ssids; local->hw_scan_req->req.ssids = req->ssids;
local->hw_scan_req->req.n_ssids = req->n_ssids; local->hw_scan_req->req.n_ssids = req->n_ssids;
/* None of the channels are actually set
* up but let UBSAN know the boundaries.
*/
local->hw_scan_req->req.n_channels = req->n_channels;
ies = (u8 *)local->hw_scan_req + ies = (u8 *)local->hw_scan_req +
sizeof(*local->hw_scan_req) + sizeof(*local->hw_scan_req) +
req->n_channels * sizeof(req->channels[0]); req->n_channels * sizeof(req->channels[0]);

View File

@@ -42,8 +42,8 @@ void ieee802154_xmit_worker(struct work_struct *work)
if (res) if (res)
goto err_tx; goto err_tx;
dev->stats.tx_packets++; DEV_STATS_INC(dev, tx_packets);
dev->stats.tx_bytes += skb->len; DEV_STATS_ADD(dev, tx_bytes, skb->len);
ieee802154_xmit_complete(&local->hw, skb, false); ieee802154_xmit_complete(&local->hw, skb, false);
@@ -94,8 +94,8 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
goto err_tx; goto err_tx;
} }
dev->stats.tx_packets++; DEV_STATS_INC(dev, tx_packets);
dev->stats.tx_bytes += len; DEV_STATS_ADD(dev, tx_bytes, len);
} else { } else {
local->tx_skb = skb; local->tx_skb = skb;
queue_work(local->workqueue, &local->tx_work); queue_work(local->workqueue, &local->tx_work);

View File

@@ -1893,10 +1893,14 @@ int cfg80211_wext_siwscan(struct net_device *dev,
wiphy = &rdev->wiphy; wiphy = &rdev->wiphy;
/* Determine number of channels, needed to allocate creq */ /* Determine number of channels, needed to allocate creq */
if (wreq && wreq->num_channels) if (wreq && wreq->num_channels) {
/* Passed from userspace so should be checked */
if (unlikely(wreq->num_channels > IW_MAX_FREQUENCIES))
return -EINVAL;
n_channels = wreq->num_channels; n_channels = wreq->num_channels;
else } else {
n_channels = ieee80211_get_num_supported_channels(wiphy); n_channels = ieee80211_get_num_supported_channels(wiphy);
}
creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
n_channels * sizeof(void *), n_channels * sizeof(void *),

View File

@@ -977,4 +977,8 @@ static inline void debug_gimple_stmt(const_gimple s)
#define SET_DECL_MODE(decl, mode) DECL_MODE(decl) = (mode) #define SET_DECL_MODE(decl, mode) DECL_MODE(decl) = (mode)
#endif #endif
#if BUILDING_GCC_VERSION >= 14000
#define last_stmt(x) last_nondebug_stmt(x)
#endif
#endif #endif

View File

@@ -395,35 +395,6 @@ static struct expr *expr_eliminate_yn(struct expr *e)
return e; return e;
} }
/*
* bool FOO!=n => FOO
*/
struct expr *expr_trans_bool(struct expr *e)
{
if (!e)
return NULL;
switch (e->type) {
case E_AND:
case E_OR:
case E_NOT:
e->left.expr = expr_trans_bool(e->left.expr);
e->right.expr = expr_trans_bool(e->right.expr);
break;
case E_UNEQUAL:
// FOO!=n -> FOO
if (e->left.sym->type == S_TRISTATE) {
if (e->right.sym == &symbol_no) {
e->type = E_SYMBOL;
e->right.sym = NULL;
}
}
break;
default:
;
}
return e;
}
/* /*
* e1 || e2 -> ? * e1 || e2 -> ?
*/ */

View File

@@ -302,7 +302,6 @@ struct expr *expr_copy(const struct expr *org);
void expr_free(struct expr *e); void expr_free(struct expr *e);
void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
tristate expr_calc_value(struct expr *e); tristate expr_calc_value(struct expr *e);
struct expr *expr_trans_bool(struct expr *e);
struct expr *expr_eliminate_dups(struct expr *e); struct expr *expr_eliminate_dups(struct expr *e);
struct expr *expr_transform(struct expr *e); struct expr *expr_transform(struct expr *e);
int expr_contains_symbol(struct expr *dep, struct symbol *sym); int expr_contains_symbol(struct expr *dep, struct symbol *sym);

View File

@@ -1485,7 +1485,6 @@ int main(int ac, char *av[])
conf_parse(name); conf_parse(name);
fixup_rootmenu(&rootmenu); fixup_rootmenu(&rootmenu);
conf_read(NULL);
/* Load the interface and connect signals */ /* Load the interface and connect signals */
init_main_window(glade_file); init_main_window(glade_file);
@@ -1493,6 +1492,8 @@ int main(int ac, char *av[])
init_left_tree(); init_left_tree();
init_right_tree(); init_right_tree();
conf_read(NULL);
switch (view_mode) { switch (view_mode) {
case SINGLE_VIEW: case SINGLE_VIEW:
display_tree_part(); display_tree_part();

View File

@@ -390,8 +390,6 @@ void menu_finalize(struct menu *parent)
dep = expr_transform(dep); dep = expr_transform(dep);
dep = expr_alloc_and(expr_copy(basedep), dep); dep = expr_alloc_and(expr_copy(basedep), dep);
dep = expr_eliminate_dups(dep); dep = expr_eliminate_dups(dep);
if (menu->sym && menu->sym->type != S_TRISTATE)
dep = expr_trans_bool(dep);
prop->visible.expr = dep; prop->visible.expr = dep;
/* /*

View File

@@ -354,6 +354,12 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream) int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
{ {
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
struct dma_tx_state state;
enum dma_status status;
status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state);
if (status == DMA_PAUSED)
dmaengine_terminate_async(prtd->dma_chan);
dmaengine_synchronize(prtd->dma_chan); dmaengine_synchronize(prtd->dma_chan);
kfree(prtd); kfree(prtd);
@@ -371,6 +377,12 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream) int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream)
{ {
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
struct dma_tx_state state;
enum dma_status status;
status = dmaengine_tx_status(prtd->dma_chan, prtd->cookie, &state);
if (status == DMA_PAUSED)
dmaengine_terminate_async(prtd->dma_chan);
dmaengine_synchronize(prtd->dma_chan); dmaengine_synchronize(prtd->dma_chan);
dma_release_channel(prtd->dma_chan); dma_release_channel(prtd->dma_chan);

View File

@@ -474,6 +474,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
BYT_RT5640_SSP0_AIF1 | BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN), BYT_RT5640_MCLK_EN),
}, },
{
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 CESIUM"),
},
.driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
BYT_RT5640_JD_NOT_INV |
BYT_RT5640_DIFF_MIC |
BYT_RT5640_SSP0_AIF1 |
BYT_RT5640_MCLK_EN),
},
{ {
.matches = { .matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"),

View File

@@ -77,14 +77,20 @@ static struct vdso_info
ELF(Verdef) *verdef; ELF(Verdef) *verdef;
} vdso_info; } vdso_info;
/* Straight from the ELF specification. */ /*
static unsigned long elf_hash(const unsigned char *name) * Straight from the ELF specification...and then tweaked slightly, in order to
* avoid a few clang warnings.
*/
static unsigned long elf_hash(const char *name)
{ {
unsigned long h = 0, g; unsigned long h = 0, g;
while (*name) const unsigned char *uch_name = (const unsigned char *)name;
while (*uch_name)
{ {
h = (h << 4) + *name++; h = (h << 4) + *uch_name++;
if (g = h & 0xf0000000) g = h & 0xf0000000;
if (g)
h ^= g >> 24; h ^= g >> 24;
h &= ~g; h &= ~g;
} }

View File

@@ -20,7 +20,7 @@ extern void *vdso_sym(const char *version, const char *name);
extern void vdso_init_from_sysinfo_ehdr(uintptr_t base); extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
extern void vdso_init_from_auxv(void *auxv); extern void vdso_init_from_auxv(void *auxv);
/* We need a libc functions... */ /* We need some libc functions... */
int strcmp(const char *a, const char *b) int strcmp(const char *a, const char *b)
{ {
/* This implementation is buggy: it never returns -1. */ /* This implementation is buggy: it never returns -1. */
@@ -36,6 +36,20 @@ int strcmp(const char *a, const char *b)
return 0; return 0;
} }
/*
* The clang build needs this, although gcc does not.
* Stolen from lib/string.c.
*/
void *memcpy(void *dest, const void *src, size_t count)
{
char *tmp = dest;
const char *s = src;
while (count--)
*tmp++ = *s++;
return dest;
}
/* ...and two syscalls. This is x86-specific. */ /* ...and two syscalls. This is x86-specific. */
static inline long x86_syscall3(long nr, long a0, long a1, long a2) static inline long x86_syscall3(long nr, long a0, long a1, long a2)
{ {
@@ -72,7 +86,7 @@ void to_base10(char *lastdig, time_t n)
} }
} }
__attribute__((externally_visible)) void c_main(void **stack) void c_main(void **stack)
{ {
/* Parse the stack */ /* Parse the stack */
long argc = (long)*stack; long argc = (long)*stack;