Merge branch 'lsk-v4.4-android' of git://android.git.linaro.org/kernel/linaro-android into linux-linaro-lsk-v4.4-android

This commit is contained in:
Alex Shi 2016-06-02 17:59:02 +08:00
commit cf5ba83bb2
46 changed files with 198 additions and 1103 deletions

View File

@ -57,6 +57,7 @@ CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
@ -138,6 +139,7 @@ CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
CONFIG_PREEMPT=y
CONFIG_QUOTA=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_RTC_CLASS=y
CONFIG_RT_GROUP_SCHED=y
@ -146,7 +148,6 @@ CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SETEND_EMULATION=y
CONFIG_STAGING=y
CONFIG_SWITCH=y
CONFIG_SWP_EMULATION=y
CONFIG_SYNC=y
CONFIG_TUN=y

View File

@ -119,7 +119,6 @@ CONFIG_TIMER_STATS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_UHID=y
CONFIG_UID_STAT=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_HIDDEV=y

View File

@ -1,28 +0,0 @@
/*
* arch/arm/include/asm/mach/mmc.h
*/
#ifndef ASMARM_MACH_MMC_H
#define ASMARM_MACH_MMC_H
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/mmc/sdio_func.h>
struct embedded_sdio_data {
struct sdio_cis cis;
struct sdio_cccr cccr;
struct sdio_embedded_func *funcs;
int num_funcs;
};
struct mmc_platform_data {
unsigned int ocr_mask; /* available voltages */
int built_in; /* built-in device flag */
int card_present; /* card detect state */
u32 (*translate_vdd)(struct device *, unsigned int);
unsigned int (*status)(struct device *);
struct embedded_sdio_data *embedded_sdio;
int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
};
#endif

View File

@ -104,8 +104,6 @@ source "drivers/memstick/Kconfig"
source "drivers/leds/Kconfig"
source "drivers/switch/Kconfig"
source "drivers/accessibility/Kconfig"
source "drivers/infiniband/Kconfig"

View File

@ -122,7 +122,6 @@ obj-$(CONFIG_CPU_IDLE) += cpuidle/
obj-y += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/
obj-y += leds/
obj-$(CONFIG_SWITCH) += switch/
obj-$(CONFIG_INFINIBAND) += infiniband/
obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/

View File

@ -35,8 +35,6 @@
#include <linux/timer.h>
#include <linux/wakeup_reason.h>
#include <asm/current.h>
#include "../base.h"
#include "power.h"
@ -62,12 +60,6 @@ struct suspend_stats suspend_stats;
static DEFINE_MUTEX(dpm_list_mtx);
static pm_message_t pm_transition;
static void dpm_drv_timeout(unsigned long data);
struct dpm_drv_wd_data {
struct device *dev;
struct task_struct *tsk;
};
static int async_error;
static char *pm_verb(int event)
@ -838,30 +830,6 @@ static void async_resume(void *data, async_cookie_t cookie)
put_device(dev);
}
/**
* dpm_drv_timeout - Driver suspend / resume watchdog handler
* @data: struct device which timed out
*
* Called when a driver has timed out suspending or resuming.
* There's not much we can do here to recover so
* BUG() out for a crash-dump
*
*/
static void dpm_drv_timeout(unsigned long data)
{
struct dpm_drv_wd_data *wd_data = (void *)data;
struct device *dev = wd_data->dev;
struct task_struct *tsk = wd_data->tsk;
printk(KERN_EMERG "**** DPM device timeout: %s (%s)\n", dev_name(dev),
(dev->driver ? dev->driver->name : "no driver"));
printk(KERN_EMERG "dpm suspend stack:\n");
show_stack(tsk, NULL);
BUG();
}
/**
* dpm_resume - Execute "resume" callbacks for non-sysdev devices.
* @state: PM transition of the system being carried out.
@ -1380,8 +1348,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
pm_callback_t callback = NULL;
char *info = NULL;
int error = 0;
struct timer_list timer;
struct dpm_drv_wd_data data;
char suspend_abort[MAX_SUSPEND_ABORT_LEN];
DECLARE_DPM_WATCHDOG_ON_STACK(wd);
@ -1412,14 +1378,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
if (dev->power.syscore)
goto Complete;
data.dev = dev;
data.tsk = current;
init_timer_on_stack(&timer);
timer.expires = jiffies + HZ * 12;
timer.function = dpm_drv_timeout;
timer.data = (unsigned long)&data;
add_timer(&timer);
if (dev->power.direct_complete) {
if (pm_runtime_status_suspended(dev)) {
@ -1500,9 +1458,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
device_unlock(dev);
dpm_watchdog_clear(&wd);
del_timer_sync(&timer);
destroy_timer_on_stack(&timer);
Complete:
complete_all(&dev->power.completion);
if (error)

View File

@ -116,28 +116,6 @@ struct cpufreq_interactive_tunables {
bool io_is_busy;
};
/*
* HACK: FIXME: Bring back cpufreq_{get,put}_global_kobject()
* definition removed by upstream commit 8eec1020f0c0 "cpufreq:
* create cpu/cpufreq at boot time" to fix build failures.
*/
static int cpufreq_global_kobject_usage;
int cpufreq_get_global_kobject(void)
{
if (!cpufreq_global_kobject_usage++)
return kobject_add(cpufreq_global_kobject,
&cpu_subsys.dev_root->kobj, "%s", "cpufreq");
return 0;
}
void cpufreq_put_global_kobject(void)
{
if (!--cpufreq_global_kobject_usage)
kobject_del(cpufreq_global_kobject);
}
/* For cases where we have single governor instance for system */
static struct cpufreq_interactive_tunables *common_tunables;
@ -1206,7 +1184,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
policy->governor_data = tunables;
if (!have_governor_per_policy()) {
common_tunables = tunables;
WARN_ON(cpufreq_get_global_kobject());
}
rc = sysfs_create_group(get_governor_parent_kobj(policy),
@ -1216,7 +1193,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
policy->governor_data = NULL;
if (!have_governor_per_policy()) {
common_tunables = NULL;
cpufreq_put_global_kobject();
}
return rc;
}
@ -1240,9 +1216,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
sysfs_remove_group(get_governor_parent_kobj(policy),
get_sysfs_attr());
if (!have_governor_per_policy())
cpufreq_put_global_kobject();
kfree(tunables);
common_tunables = NULL;
}

View File

@ -450,16 +450,6 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
td->buttons_count++;
/* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections
* such as Mouse that might have the same GenericDesktop usages. */
if (field->application == HID_DG_TOUCHSCREEN)
set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
else if (field->application == HID_DG_TOUCHPAD)
set_bit(INPUT_PROP_POINTER, hi->input->propbit);
else
return 0;
if (usage->usage_index)
prev_usage = &field->usage[usage->usage_index - 1];

View File

@ -253,11 +253,6 @@ static int steelseries_srws1_probe(struct hid_device *hdev,
goto err_free;
}
if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 16)) {
ret = -ENODEV;
goto err_free;
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
hid_err(hdev, "hw start failed\n");

View File

@ -412,10 +412,6 @@ config TI_DAC7512
This driver can also be built as a module. If so, the module
will be called ti_dac7512.
config UID_STAT
bool "UID based statistics tracking exported to /proc/uid_stat"
default n
config VMWARE_BALLOON
tristate "VMware Balloon Driver"
depends on VMWARE_VMCI && X86 && HYPERVISOR_GUEST

View File

@ -35,7 +35,6 @@ obj-$(CONFIG_ISL29020) += isl29020.o
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
obj-$(CONFIG_DS1682) += ds1682.o
obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o
obj-$(CONFIG_UID_STAT) += uid_stat.o
obj-$(CONFIG_C2PORT) += c2port/
obj-$(CONFIG_HMC6352) += hmc6352.o
obj-y += eeprom/

View File

@ -1,153 +0,0 @@
/* drivers/misc/uid_stat.c
*
* Copyright (C) 2008 - 2009 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/atomic.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/stat.h>
#include <linux/uid_stat.h>
#include <net/activity_stats.h>
static DEFINE_SPINLOCK(uid_lock);
static LIST_HEAD(uid_list);
static struct proc_dir_entry *parent;
struct uid_stat {
struct list_head link;
uid_t uid;
atomic_t tcp_rcv;
atomic_t tcp_snd;
};
static struct uid_stat *find_uid_stat(uid_t uid) {
struct uid_stat *entry;
list_for_each_entry(entry, &uid_list, link) {
if (entry->uid == uid) {
return entry;
}
}
return NULL;
}
static int uid_stat_atomic_int_show(struct seq_file *m, void *v)
{
unsigned int bytes;
atomic_t *counter = m->private;
bytes = (unsigned int) (atomic_read(counter) + INT_MIN);
seq_printf(m, "%u\n", bytes);
return seq_has_overflowed(m) ? -ENOSPC : 0;
}
static int uid_stat_read_atomic_int_open(struct inode *inode, struct file *file)
{
return single_open(file, uid_stat_atomic_int_show, PDE_DATA(inode));
}
static const struct file_operations uid_stat_read_atomic_int_fops = {
.open = uid_stat_read_atomic_int_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
/* Create a new entry for tracking the specified uid. */
static struct uid_stat *create_stat(uid_t uid) {
struct uid_stat *new_uid;
/* Create the uid stat struct and append it to the list. */
new_uid = kmalloc(sizeof(struct uid_stat), GFP_ATOMIC);
if (!new_uid)
return NULL;
new_uid->uid = uid;
/* Counters start at INT_MIN, so we can track 4GB of network traffic. */
atomic_set(&new_uid->tcp_rcv, INT_MIN);
atomic_set(&new_uid->tcp_snd, INT_MIN);
list_add_tail(&new_uid->link, &uid_list);
return new_uid;
}
static void create_stat_proc(struct uid_stat *new_uid)
{
char uid_s[32];
struct proc_dir_entry *entry;
sprintf(uid_s, "%d", new_uid->uid);
entry = proc_mkdir(uid_s, parent);
/* Keep reference to uid_stat so we know what uid to read stats from. */
proc_create_data("tcp_snd", S_IRUGO, entry,
&uid_stat_read_atomic_int_fops, &new_uid->tcp_snd);
proc_create_data("tcp_rcv", S_IRUGO, entry,
&uid_stat_read_atomic_int_fops, &new_uid->tcp_rcv);
}
static struct uid_stat *find_or_create_uid_stat(uid_t uid)
{
struct uid_stat *entry;
unsigned long flags;
spin_lock_irqsave(&uid_lock, flags);
entry = find_uid_stat(uid);
if (entry) {
spin_unlock_irqrestore(&uid_lock, flags);
return entry;
}
entry = create_stat(uid);
spin_unlock_irqrestore(&uid_lock, flags);
if (entry)
create_stat_proc(entry);
return entry;
}
int uid_stat_tcp_snd(uid_t uid, int size) {
struct uid_stat *entry;
activity_stats_update();
entry = find_or_create_uid_stat(uid);
if (!entry)
return -1;
atomic_add(size, &entry->tcp_snd);
return 0;
}
int uid_stat_tcp_rcv(uid_t uid, int size) {
struct uid_stat *entry;
activity_stats_update();
entry = find_or_create_uid_stat(uid);
if (!entry)
return -1;
atomic_add(size, &entry->tcp_rcv);
return 0;
}
static int __init uid_stat_init(void)
{
parent = proc_mkdir("uid_stat", NULL);
if (!parent) {
pr_err("uid_stat: failed to create proc entry\n");
return -1;
}
return 0;
}
__initcall(uid_stat_init);

View File

@ -549,6 +549,11 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
int ret;
/* Disable filtering */
ret = wl1271_acx_group_address_tbl(wl, wlvif, false, NULL, 0);
if (ret < 0)
return ret;
ret = wl1271_acx_ap_max_tx_retry(wl, wlvif);
if (ret < 0)
return ret;

View File

@ -42,6 +42,15 @@ config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
If enabled, this puts the fiq debugger into console mode by default.
Otherwise, the fiq debugger will start out in debug mode.
config FIQ_DEBUGGER_UART_OVERLAY
bool "Install uart DT overlay"
depends on FIQ_DEBUGGER
select OF_OVERLAY
default n
help
If enabled, fiq debugger is calling fiq_debugger_uart_overlay()
that will apply overlay uart_overlay@0 to disable proper uart.
config FIQ_WATCHDOG
bool
select FIQ_DEBUGGER

View File

@ -39,6 +39,10 @@
#include <asm/fiq_glue.h>
#endif
#ifdef CONFIG_FIQ_DEBUGGER_UART_OVERLAY
#include <linux/of.h>
#endif
#include <linux/uaccess.h>
#include "fiq_debugger.h"
@ -119,11 +123,13 @@ static bool initial_console_enable;
#endif
static bool fiq_kgdb_enable;
static bool fiq_debugger_disable;
module_param_named(no_sleep, initial_no_sleep, bool, 0644);
module_param_named(debug_enable, initial_debug_enable, bool, 0644);
module_param_named(console_enable, initial_console_enable, bool, 0644);
module_param_named(kgdb_enable, fiq_kgdb_enable, bool, 0644);
module_param_named(disable, fiq_debugger_disable, bool, 0644);
#ifdef CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
static inline
@ -1201,10 +1207,40 @@ static struct platform_driver fiq_debugger_driver = {
},
};
#if defined(CONFIG_FIQ_DEBUGGER_UART_OVERLAY)
int fiq_debugger_uart_overlay(void)
{
struct device_node *onp = of_find_node_by_path("/uart_overlay@0");
int ret;
if (!onp) {
pr_err("serial_debugger: uart overlay not found\n");
return -ENODEV;
}
ret = of_overlay_create(onp);
if (ret < 0) {
pr_err("serial_debugger: fail to create overlay: %d\n", ret);
of_node_put(onp);
return ret;
}
pr_info("serial_debugger: uart overlay applied\n");
return 0;
}
#endif
static int __init fiq_debugger_init(void)
{
if (fiq_debugger_disable) {
pr_err("serial_debugger: disabled\n");
return -ENODEV;
}
#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
fiq_debugger_tty_init();
#endif
#if defined(CONFIG_FIQ_DEBUGGER_UART_OVERLAY)
fiq_debugger_uart_overlay();
#endif
return platform_driver_register(&fiq_debugger_driver);
}

View File

@ -1,15 +0,0 @@
menuconfig SWITCH
tristate "Switch class support"
help
Say Y here to enable switch class support. This allows
monitoring switches by userspace via sysfs and uevent.
if SWITCH
config SWITCH_GPIO
tristate "GPIO Swith support"
depends on GPIOLIB
help
Say Y here to enable GPIO based switch support.
endif # SWITCH

View File

@ -1,4 +0,0 @@
# Switch Class Driver
obj-$(CONFIG_SWITCH) += switch_class.o
obj-$(CONFIG_SWITCH_GPIO) += switch_gpio.o

View File

@ -1,174 +0,0 @@
/*
* drivers/switch/switch_class.c
*
* Copyright (C) 2008 Google, Inc.
* Author: Mike Lockwood <lockwood@android.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/err.h>
#include <linux/switch.h>
struct class *switch_class;
static atomic_t device_count;
static ssize_t state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct switch_dev *sdev = (struct switch_dev *)
dev_get_drvdata(dev);
if (sdev->print_state) {
int ret = sdev->print_state(sdev, buf);
if (ret >= 0)
return ret;
}
return sprintf(buf, "%d\n", sdev->state);
}
static ssize_t name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct switch_dev *sdev = (struct switch_dev *)
dev_get_drvdata(dev);
if (sdev->print_name) {
int ret = sdev->print_name(sdev, buf);
if (ret >= 0)
return ret;
}
return sprintf(buf, "%s\n", sdev->name);
}
static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
static DEVICE_ATTR(name, S_IRUGO, name_show, NULL);
void switch_set_state(struct switch_dev *sdev, int state)
{
char name_buf[120];
char state_buf[120];
char *prop_buf;
char *envp[3];
int env_offset = 0;
int length;
if (sdev->state != state) {
sdev->state = state;
prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
if (prop_buf) {
length = name_show(sdev->dev, NULL, prop_buf);
if (length > 0) {
if (prop_buf[length - 1] == '\n')
prop_buf[length - 1] = 0;
snprintf(name_buf, sizeof(name_buf),
"SWITCH_NAME=%s", prop_buf);
envp[env_offset++] = name_buf;
}
length = state_show(sdev->dev, NULL, prop_buf);
if (length > 0) {
if (prop_buf[length - 1] == '\n')
prop_buf[length - 1] = 0;
snprintf(state_buf, sizeof(state_buf),
"SWITCH_STATE=%s", prop_buf);
envp[env_offset++] = state_buf;
}
envp[env_offset] = NULL;
kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp);
free_page((unsigned long)prop_buf);
} else {
printk(KERN_ERR "out of memory in switch_set_state\n");
kobject_uevent(&sdev->dev->kobj, KOBJ_CHANGE);
}
}
}
EXPORT_SYMBOL_GPL(switch_set_state);
static int create_switch_class(void)
{
if (!switch_class) {
switch_class = class_create(THIS_MODULE, "switch");
if (IS_ERR(switch_class))
return PTR_ERR(switch_class);
atomic_set(&device_count, 0);
}
return 0;
}
int switch_dev_register(struct switch_dev *sdev)
{
int ret;
if (!switch_class) {
ret = create_switch_class();
if (ret < 0)
return ret;
}
sdev->index = atomic_inc_return(&device_count);
sdev->dev = device_create(switch_class, NULL,
MKDEV(0, sdev->index), NULL, sdev->name);
if (IS_ERR(sdev->dev))
return PTR_ERR(sdev->dev);
ret = device_create_file(sdev->dev, &dev_attr_state);
if (ret < 0)
goto err_create_file_1;
ret = device_create_file(sdev->dev, &dev_attr_name);
if (ret < 0)
goto err_create_file_2;
dev_set_drvdata(sdev->dev, sdev);
sdev->state = 0;
return 0;
err_create_file_2:
device_remove_file(sdev->dev, &dev_attr_state);
err_create_file_1:
device_destroy(switch_class, MKDEV(0, sdev->index));
printk(KERN_ERR "switch: Failed to register driver %s\n", sdev->name);
return ret;
}
EXPORT_SYMBOL_GPL(switch_dev_register);
void switch_dev_unregister(struct switch_dev *sdev)
{
device_remove_file(sdev->dev, &dev_attr_name);
device_remove_file(sdev->dev, &dev_attr_state);
device_destroy(switch_class, MKDEV(0, sdev->index));
dev_set_drvdata(sdev->dev, NULL);
}
EXPORT_SYMBOL_GPL(switch_dev_unregister);
static int __init switch_class_init(void)
{
return create_switch_class();
}
static void __exit switch_class_exit(void)
{
class_destroy(switch_class);
}
module_init(switch_class_init);
module_exit(switch_class_exit);
MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
MODULE_DESCRIPTION("Switch class driver");
MODULE_LICENSE("GPL");

View File

@ -1,172 +0,0 @@
/*
* drivers/switch/switch_gpio.c
*
* Copyright (C) 2008 Google, Inc.
* Author: Mike Lockwood <lockwood@android.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/switch.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
struct gpio_switch_data {
struct switch_dev sdev;
unsigned gpio;
const char *name_on;
const char *name_off;
const char *state_on;
const char *state_off;
int irq;
struct work_struct work;
};
static void gpio_switch_work(struct work_struct *work)
{
int state;
struct gpio_switch_data *data =
container_of(work, struct gpio_switch_data, work);
state = gpio_get_value(data->gpio);
switch_set_state(&data->sdev, state);
}
static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
{
struct gpio_switch_data *switch_data =
(struct gpio_switch_data *)dev_id;
schedule_work(&switch_data->work);
return IRQ_HANDLED;
}
static ssize_t switch_gpio_print_state(struct switch_dev *sdev, char *buf)
{
struct gpio_switch_data *switch_data =
container_of(sdev, struct gpio_switch_data, sdev);
const char *state;
if (switch_get_state(sdev))
state = switch_data->state_on;
else
state = switch_data->state_off;
if (state)
return sprintf(buf, "%s\n", state);
return -1;
}
static int gpio_switch_probe(struct platform_device *pdev)
{
struct gpio_switch_platform_data *pdata = pdev->dev.platform_data;
struct gpio_switch_data *switch_data;
int ret = 0;
if (!pdata)
return -EBUSY;
switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL);
if (!switch_data)
return -ENOMEM;
switch_data->sdev.name = pdata->name;
switch_data->gpio = pdata->gpio;
switch_data->name_on = pdata->name_on;
switch_data->name_off = pdata->name_off;
switch_data->state_on = pdata->state_on;
switch_data->state_off = pdata->state_off;
switch_data->sdev.print_state = switch_gpio_print_state;
ret = switch_dev_register(&switch_data->sdev);
if (ret < 0)
goto err_switch_dev_register;
ret = gpio_request(switch_data->gpio, pdev->name);
if (ret < 0)
goto err_request_gpio;
ret = gpio_direction_input(switch_data->gpio);
if (ret < 0)
goto err_set_gpio_input;
INIT_WORK(&switch_data->work, gpio_switch_work);
switch_data->irq = gpio_to_irq(switch_data->gpio);
if (switch_data->irq < 0) {
ret = switch_data->irq;
goto err_detect_irq_num_failed;
}
ret = request_irq(switch_data->irq, gpio_irq_handler,
IRQF_TRIGGER_LOW, pdev->name, switch_data);
if (ret < 0)
goto err_request_irq;
/* Perform initial detection */
gpio_switch_work(&switch_data->work);
return 0;
err_request_irq:
err_detect_irq_num_failed:
err_set_gpio_input:
gpio_free(switch_data->gpio);
err_request_gpio:
switch_dev_unregister(&switch_data->sdev);
err_switch_dev_register:
kfree(switch_data);
return ret;
}
static int gpio_switch_remove(struct platform_device *pdev)
{
struct gpio_switch_data *switch_data = platform_get_drvdata(pdev);
cancel_work_sync(&switch_data->work);
gpio_free(switch_data->gpio);
switch_dev_unregister(&switch_data->sdev);
kfree(switch_data);
return 0;
}
static struct platform_driver gpio_switch_driver = {
.probe = gpio_switch_probe,
.remove = gpio_switch_remove,
.driver = {
.name = "switch-gpio",
.owner = THIS_MODULE,
},
};
static int __init gpio_switch_init(void)
{
return platform_driver_register(&gpio_switch_driver);
}
static void __exit gpio_switch_exit(void)
{
platform_driver_unregister(&gpio_switch_driver);
}
module_init(gpio_switch_init);
module_exit(gpio_switch_exit);
MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
MODULE_DESCRIPTION("GPIO Switch driver");
MODULE_LICENSE("GPL");

View File

@ -13,6 +13,7 @@
#include <linux/poll.h>
#include <linux/uio.h>
#include <linux/miscdevice.h>
#include <linux/namei.h>
#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/slab.h>
@ -1935,6 +1936,10 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
cs->move_pages = 0;
err = copy_out_args(cs, &req->out, nbytes);
if (req->in.h.opcode == FUSE_CANONICAL_PATH) {
req->out.h.error = kern_path((char *)req->out.args[0].value, 0,
req->canonical_path);
}
fuse_copy_finish(cs);
spin_lock(&fpq->lock);

View File

@ -267,6 +267,50 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
goto out;
}
/*
* Get the canonical path. Since we must translate to a path, this must be done
* in the context of the userspace daemon, however, the userspace daemon cannot
* look up paths on its own. Instead, we handle the lookup as a special case
* inside of the write request.
*/
static void fuse_dentry_canonical_path(const struct path *path, struct path *canonical_path) {
struct inode *inode = path->dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
int err;
char *path_name;
req = fuse_get_req(fc, 1);
err = PTR_ERR(req);
if (IS_ERR(req))
goto default_path;
path_name = (char*)__get_free_page(GFP_KERNEL);
if (!path_name) {
fuse_put_request(fc, req);
goto default_path;
}
req->in.h.opcode = FUSE_CANONICAL_PATH;
req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 0;
req->out.numargs = 1;
req->out.args[0].size = PATH_MAX;
req->out.args[0].value = path_name;
req->canonical_path = canonical_path;
req->out.argvar = 1;
fuse_request_send(fc, req);
err = req->out.h.error;
fuse_put_request(fc, req);
free_page((unsigned long)path_name);
if (!err)
return;
default_path:
canonical_path->dentry = path->dentry;
canonical_path->mnt = path->mnt;
path_get(canonical_path);
}
static int invalid_nodeid(u64 nodeid)
{
return !nodeid || nodeid == FUSE_ROOT_ID;
@ -274,6 +318,7 @@ static int invalid_nodeid(u64 nodeid)
const struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
.d_canonical_path = fuse_dentry_canonical_path,
};
int fuse_valid_type(int m)

View File

@ -372,6 +372,9 @@ struct fuse_req {
/** Inode used in the request or NULL */
struct inode *inode;
/** Path used for completing d_canonical_path */
struct path *canonical_path;
/** AIO control block */
struct fuse_io_priv *io;

View File

@ -746,7 +746,7 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
/* support stacked filesystems */
if(path.dentry && path.dentry->d_op) {
if (path.dentry->d_op->d_canonical_path) {
path.dentry->d_op->d_canonical_path(path.dentry, &alteredpath);
path.dentry->d_op->d_canonical_path(&path, &alteredpath);
canonical_path = &alteredpath;
path_put(&path);
}

View File

@ -3078,6 +3078,44 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
return 0;
}
/*
* proc_tid_comm_permission is a special permission function exclusively
* used for the node /proc/<pid>/task/<tid>/comm.
* It bypasses generic permission checks in the case where a task of the same
* task group attempts to access the node.
* The rational behind this is that glibc and bionic access this node for
* cross thread naming (pthread_set/getname_np(!self)). However, if
* PR_SET_DUMPABLE gets set to 0 this node among others becomes uid=0 gid=0,
* which locks out the cross thread naming implementation.
* This function makes sure that the node is always accessible for members of
* same thread group.
*/
static int proc_tid_comm_permission(struct inode *inode, int mask)
{
bool is_same_tgroup;
struct task_struct *task;
task = get_proc_task(inode);
if (!task)
return -ESRCH;
is_same_tgroup = same_thread_group(current, task);
put_task_struct(task);
if (likely(is_same_tgroup && !(mask & MAY_EXEC))) {
/* This file (/proc/<pid>/task/<tid>/comm) can always be
* read or written by the members of the corresponding
* thread group.
*/
return 0;
}
return generic_permission(inode, mask);
}
static const struct inode_operations proc_tid_comm_inode_operations = {
.permission = proc_tid_comm_permission,
};
/*
* Tasks
*/
@ -3096,7 +3134,9 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
NOD("comm", S_IFREG|S_IRUGO|S_IWUSR,
&proc_tid_comm_inode_operations,
&proc_pid_set_comm_operations, {}),
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
ONE("syscall", S_IRUSR, proc_pid_syscall),
#endif

View File

@ -172,11 +172,15 @@ static int sdcardfs_cmp_ci(const struct dentry *parent,
return 1;
}
static void sdcardfs_canonical_path(const struct path *path, struct path *actual_path) {
sdcardfs_get_real_lower(path->dentry, actual_path);
}
const struct dentry_operations sdcardfs_ci_dops = {
.d_revalidate = sdcardfs_d_revalidate,
.d_release = sdcardfs_d_release,
.d_hash = sdcardfs_hash_ci,
.d_compare = sdcardfs_cmp_ci,
.d_canonical_path = sdcardfs_get_real_lower,
.d_canonical_path = sdcardfs_canonical_path,
};

View File

@ -40,10 +40,7 @@ struct mmci_platform_data {
int gpio_wp;
int gpio_cd;
bool cd_invert;
unsigned int status_irq;
struct embedded_sdio_data *embedded_sdio;
int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
};
#endif

View File

@ -161,7 +161,7 @@ struct dentry_operations {
struct vfsmount *(*d_automount)(struct path *);
int (*d_manage)(struct dentry *, bool);
struct inode *(*d_select_inode)(struct dentry *, unsigned);
void (*d_canonical_path)(const struct dentry *, struct path *);
void (*d_canonical_path)(const struct path *, struct path *);
struct dentry *(*d_real)(struct dentry *, struct inode *);
} ____cacheline_aligned;

View File

@ -1,53 +0,0 @@
/*
* Switch class driver
*
* Copyright (C) 2008 Google, Inc.
* Author: Mike Lockwood <lockwood@android.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __LINUX_SWITCH_H__
#define __LINUX_SWITCH_H__
struct switch_dev {
const char *name;
struct device *dev;
int index;
int state;
ssize_t (*print_name)(struct switch_dev *sdev, char *buf);
ssize_t (*print_state)(struct switch_dev *sdev, char *buf);
};
struct gpio_switch_platform_data {
const char *name;
unsigned gpio;
/* if NULL, switch_dev.name will be printed */
const char *name_on;
const char *name_off;
/* if NULL, "0" or "1" will be printed */
const char *state_on;
const char *state_off;
};
extern int switch_dev_register(struct switch_dev *sdev);
extern void switch_dev_unregister(struct switch_dev *sdev);
static inline int switch_get_state(struct switch_dev *sdev)
{
return sdev->state;
}
extern void switch_set_state(struct switch_dev *sdev, int state);
#endif /* __LINUX_SWITCH_H__ */

View File

@ -1,29 +0,0 @@
/* include/linux/uid_stat.h
*
* Copyright (C) 2008-2009 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __uid_stat_h
#define __uid_stat_h
/* Contains definitions for resource tracking per uid. */
#ifdef CONFIG_UID_STAT
int uid_stat_tcp_snd(uid_t uid, int size);
int uid_stat_tcp_rcv(uid_t uid, int size);
#else
#define uid_stat_tcp_snd(uid, size) do {} while (0);
#define uid_stat_tcp_rcv(uid, size) do {} while (0);
#endif
#endif /* _LINUX_UID_STAT_H */

View File

@ -109,18 +109,19 @@ extern int dual_role_property_is_writeable(struct dual_role_phy_instance
enum dual_role_property prop);
extern void *dual_role_get_drvdata(struct dual_role_phy_instance *dual_role);
#else /* CONFIG_DUAL_ROLE_USB_INTF */
static void dual_role_instance_changed(struct dual_role_phy_instance
static inline void dual_role_instance_changed(struct dual_role_phy_instance
*dual_role){}
static struct dual_role_phy_instance *__must_check
static inline struct dual_role_phy_instance *__must_check
devm_dual_role_instance_register(struct device *parent,
const struct dual_role_phy_desc *desc)
{
return ERR_PTR(-ENOSYS);
}
static void devm_dual_role_instance_unregister(struct device *dev,
static inline void devm_dual_role_instance_unregister(struct device *dev,
struct dual_role_phy_instance
*dual_role){}
static void *dual_role_get_drvdata(struct dual_role_phy_instance *dual_role)
static inline void *dual_role_get_drvdata(struct dual_role_phy_instance
*dual_role)
{
return ERR_PTR(-ENOSYS);
}

View File

@ -1,25 +0,0 @@
/*
* Copyright (C) 2010 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Author: Mike Chan (mike@android.com)
*/
#ifndef __activity_stats_h
#define __activity_stats_h
#ifdef CONFIG_NET_ACTIVITY_STATS
void activity_stats_update(void);
#else
#define activity_stats_update(void) {}
#endif
#endif /* _NET_ACTIVITY_STATS_H */

View File

@ -1681,8 +1681,6 @@ static inline bool tcp_stream_memory_free(const struct sock *sk)
return notsent_bytes < tcp_notsent_lowat(tp);
}
extern int tcp_nuke_addr(struct net *net, struct sockaddr *addr);
#ifdef CONFIG_PROC_FS
int tcp4_proc_init(void);
void tcp4_proc_exit(void);

View File

@ -358,6 +358,7 @@ enum fuse_opcode {
FUSE_FALLOCATE = 43,
FUSE_READDIRPLUS = 44,
FUSE_RENAME2 = 45,
FUSE_CANONICAL_PATH= 2016,
/* CUSE specific operations */
CUSE_INIT = 4096,

View File

@ -65,7 +65,6 @@
#define SIOCDIFADDR 0x8936 /* delete PA address */
#define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */
#define SIOCGIFCOUNT 0x8938 /* get number of devices */
#define SIOCKILLADDR 0x8939 /* kill sockets with this local addr */
#define SIOCGIFBR 0x8940 /* Bridging support */
#define SIOCSIFBR 0x8941 /* Set bridging options */

View File

@ -46,7 +46,6 @@
#include <linux/oom.h>
#include <linux/prefetch.h>
#include <linux/printk.h>
#include <linux/debugfs.h>
#include <asm/tlbflush.h>
#include <asm/div64.h>
@ -221,39 +220,6 @@ static unsigned long get_lru_size(struct lruvec *lruvec, enum lru_list lru)
return zone_page_state(lruvec_zone(lruvec), NR_LRU_BASE + lru);
}
struct dentry *debug_file;
static int debug_shrinker_show(struct seq_file *s, void *unused)
{
struct shrinker *shrinker;
struct shrink_control sc;
sc.gfp_mask = -1;
sc.nr_to_scan = 0;
down_read(&shrinker_rwsem);
list_for_each_entry(shrinker, &shrinker_list, list) {
int num_objs;
num_objs = shrinker->count_objects(shrinker, &sc);
seq_printf(s, "%pf %d\n", shrinker->scan_objects, num_objs);
}
up_read(&shrinker_rwsem);
return 0;
}
static int debug_shrinker_open(struct inode *inode, struct file *file)
{
return single_open(file, debug_shrinker_show, inode->i_private);
}
static const struct file_operations debug_shrinker_fops = {
.open = debug_shrinker_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/*
* Add a shrinker callback to be called from the vm.
*/
@ -283,15 +249,6 @@ int register_shrinker(struct shrinker *shrinker)
}
EXPORT_SYMBOL(register_shrinker);
static int __init add_shrinker_debug(void)
{
debugfs_create_file("shrinker", 0644, NULL, NULL,
&debug_shrinker_fops);
return 0;
}
late_initcall(add_shrinker_debug);
/*
* Remove one
*/

View File

@ -92,14 +92,6 @@ config ANDROID_PARANOID_NETWORK
help
none
config NET_ACTIVITY_STATS
bool "Network activity statistics tracking"
default y
help
Network activity statistics are useful for tracking wireless
modem activity on 2G, 3G, 4G wireless networks. Counts number of
transmissions and groups them in specified time buckets.
config NETWORK_SECMARK
bool "Security Marking"
help

View File

@ -77,4 +77,3 @@ endif
ifneq ($(CONFIG_NET_L3_MASTER_DEV),)
obj-y += l3mdev/
endif
obj-$(CONFIG_NET_ACTIVITY_STATS) += activity_stats.o

View File

@ -1,118 +0,0 @@
/* net/activity_stats.c
*
* Copyright (C) 2010 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Author: Mike Chan (mike@android.com)
*/
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/suspend.h>
#include <net/net_namespace.h>
/*
* Track transmission rates in buckets (power of 2).
* 1,2,4,8...512 seconds.
*
* Buckets represent the count of network transmissions at least
* N seconds apart, where N is 1 << bucket index.
*/
#define BUCKET_MAX 10
/* Track network activity frequency */
static unsigned long activity_stats[BUCKET_MAX];
static ktime_t last_transmit;
static ktime_t suspend_time;
static DEFINE_SPINLOCK(activity_lock);
void activity_stats_update(void)
{
int i;
unsigned long flags;
ktime_t now;
s64 delta;
spin_lock_irqsave(&activity_lock, flags);
now = ktime_get();
delta = ktime_to_ns(ktime_sub(now, last_transmit));
for (i = BUCKET_MAX - 1; i >= 0; i--) {
/*
* Check if the time delta between network activity is within the
* minimum bucket range.
*/
if (delta < (1000000000ULL << i))
continue;
activity_stats[i]++;
last_transmit = now;
break;
}
spin_unlock_irqrestore(&activity_lock, flags);
}
static int activity_stats_show(struct seq_file *m, void *v)
{
int i;
seq_printf(m, "Min Bucket(sec) Count\n");
for (i = 0; i < BUCKET_MAX; i++) {
seq_printf(m, "%15d %lu\n", 1 << i, activity_stats[i]);
if (seq_has_overflowed(m))
return -ENOSPC;
}
return 0;
}
static int activity_stats_notifier(struct notifier_block *nb,
unsigned long event, void *dummy)
{
switch (event) {
case PM_SUSPEND_PREPARE:
suspend_time = ktime_get_real();
break;
case PM_POST_SUSPEND:
suspend_time = ktime_sub(ktime_get_real(), suspend_time);
last_transmit = ktime_sub(last_transmit, suspend_time);
}
return 0;
}
static int activity_stats_open(struct inode *inode, struct file *file)
{
return single_open(file, activity_stats_show, PDE_DATA(inode));
}
static const struct file_operations activity_stats_fops = {
.open = activity_stats_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static struct notifier_block activity_stats_notifier_block = {
.notifier_call = activity_stats_notifier,
};
static int __init activity_stats_init(void)
{
proc_create("activity", S_IRUGO,
init_net.proc_net_stat, &activity_stats_fops);
return register_pm_notifier(&activity_stats_notifier_block);
}
subsys_initcall(activity_stats_init);

View File

@ -886,7 +886,6 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFPFLAGS:
case SIOCGIFPFLAGS:
case SIOCSIFFLAGS:
case SIOCKILLADDR:
err = devinet_ioctl(net, cmd, (void __user *)arg);
break;
default:

View File

@ -59,7 +59,6 @@
#include <net/arp.h>
#include <net/ip.h>
#include <net/tcp.h>
#include <net/route.h>
#include <net/ip_fib.h>
#include <net/rtnetlink.h>
@ -969,7 +968,6 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
case SIOCSIFBRDADDR: /* Set the broadcast address */
case SIOCSIFDSTADDR: /* Set the destination address */
case SIOCSIFNETMASK: /* Set the netmask for the interface */
case SIOCKILLADDR: /* Nuke all sockets on this address */
ret = -EPERM;
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto out;
@ -1021,8 +1019,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
}
ret = -EADDRNOTAVAIL;
if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS
&& cmd != SIOCKILLADDR)
if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS)
goto done;
switch (cmd) {
@ -1149,9 +1146,6 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
inet_insert_ifa(ifa);
}
break;
case SIOCKILLADDR: /* Nuke all connections on this address */
ret = tcp_nuke_addr(net, (struct sockaddr *) sin);
break;
}
done:
rtnl_unlock();

View File

@ -269,16 +269,12 @@
#include <linux/crypto.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <linux/uid_stat.h>
#include <net/icmp.h>
#include <net/inet_common.h>
#include <net/tcp.h>
#include <net/xfrm.h>
#include <net/ip.h>
#include <net/ip6_route.h>
#include <net/ipv6.h>
#include <net/transp_v6.h>
#include <net/sock.h>
#include <asm/uaccess.h>
@ -1288,10 +1284,6 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
tcp_push(sk, flags, mss_now, tp->nonagle, size_goal);
out_nopush:
release_sock(sk);
if (copied + copied_syn)
uid_stat_tcp_snd(from_kuid(&init_user_ns, current_uid()),
copied + copied_syn);
return copied + copied_syn;
do_fault:
@ -1566,8 +1558,6 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
if (copied > 0) {
tcp_recv_skb(sk, seq, &offset);
tcp_cleanup_rbuf(sk, copied);
uid_stat_tcp_rcv(from_kuid(&init_user_ns, current_uid()),
copied);
}
return copied;
}
@ -1901,10 +1891,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
tcp_cleanup_rbuf(sk, copied);
release_sock(sk);
if (copied > 0)
uid_stat_tcp_rcv(from_kuid(&init_user_ns, current_uid()),
copied);
return copied;
out:
@ -1913,9 +1899,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
recv_urg:
err = tcp_recv_urg(sk, msg, len, flags);
if (err > 0)
uid_stat_tcp_rcv(from_kuid(&init_user_ns, current_uid()),
err);
goto out;
recv_sndq:
@ -3254,119 +3237,3 @@ void __init tcp_init(void)
BUG_ON(tcp_register_congestion_control(&tcp_reno) != 0);
tcp_tasklet_init();
}
static int tcp_is_local(struct net *net, __be32 addr) {
struct rtable *rt;
struct flowi4 fl4 = { .daddr = addr };
rt = ip_route_output_key(net, &fl4);
if (IS_ERR_OR_NULL(rt))
return 0;
return rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK);
}
#if defined(CONFIG_IPV6)
static int tcp_is_local6(struct net *net, struct in6_addr *addr) {
struct rt6_info *rt6 = rt6_lookup(net, addr, addr, 0, 0);
return rt6 && rt6->dst.dev && (rt6->dst.dev->flags & IFF_LOOPBACK);
}
#endif
/*
* tcp_nuke_addr - destroy all sockets on the given local address
* if local address is the unspecified address (0.0.0.0 or ::), destroy all
* sockets with local addresses that are not configured.
*/
int tcp_nuke_addr(struct net *net, struct sockaddr *addr)
{
int family = addr->sa_family;
unsigned int bucket;
struct in_addr *in;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct in6_addr *in6 = NULL;
#endif
if (family == AF_INET) {
in = &((struct sockaddr_in *)addr)->sin_addr;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
} else if (family == AF_INET6) {
in6 = &((struct sockaddr_in6 *)addr)->sin6_addr;
#endif
} else {
return -EAFNOSUPPORT;
}
for (bucket = 0; bucket <= tcp_hashinfo.ehash_mask; bucket++) {
struct hlist_nulls_node *node;
struct sock *sk;
spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
restart:
spin_lock_bh(lock);
sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
struct inet_sock *inet = inet_sk(sk);
if (sk->sk_state == TCP_TIME_WAIT) {
/*
* Sockets that are in TIME_WAIT state are
* instances of lightweight inet_timewait_sock,
* we should simply skip them (or we'll try to
* access non-existing fields and crash).
*/
continue;
}
if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
continue;
if (sock_flag(sk, SOCK_DEAD))
continue;
if (family == AF_INET) {
__be32 s4 = inet->inet_rcv_saddr;
if (s4 == LOOPBACK4_IPV6)
continue;
if (in->s_addr != s4 &&
!(in->s_addr == INADDR_ANY &&
!tcp_is_local(net, s4)))
continue;
}
#if defined(CONFIG_IPV6)
if (family == AF_INET6) {
struct in6_addr *s6;
if (!inet->pinet6)
continue;
s6 = &sk->sk_v6_rcv_saddr;
if (ipv6_addr_type(s6) == IPV6_ADDR_MAPPED)
continue;
if (!ipv6_addr_equal(in6, s6) &&
!(ipv6_addr_equal(in6, &in6addr_any) &&
!tcp_is_local6(net, s6)))
continue;
}
#endif
sock_hold(sk);
spin_unlock_bh(lock);
local_bh_disable();
bh_lock_sock(sk);
sk->sk_err = ETIMEDOUT;
sk->sk_error_report(sk);
tcp_done(sk);
bh_unlock_sock(sk);
local_bh_enable();
sock_put(sk);
goto restart;
}
spin_unlock_bh(lock);
}
return 0;
}
EXPORT_SYMBOL_GPL(tcp_nuke_addr);

View File

@ -495,21 +495,6 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
}
EXPORT_SYMBOL(inet6_getname);
int inet6_killaddr_ioctl(struct net *net, void __user *arg) {
struct in6_ifreq ireq;
struct sockaddr_in6 sin6;
if (!capable(CAP_NET_ADMIN))
return -EACCES;
if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
return -EFAULT;
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = ireq.ifr6_addr;
return tcp_nuke_addr(net, (struct sockaddr *) &sin6);
}
int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
@ -533,8 +518,6 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return addrconf_del_ifaddr(net, (void __user *) arg);
case SIOCSIFDSTADDR:
return addrconf_set_dstaddr(net, (void __user *) arg);
case SIOCKILLADDR:
return inet6_killaddr_ioctl(net, (void __user *) arg);
default:
if (!sk->sk_prot->ioctl)
return -ENOIOCTLCMD;

View File

@ -530,7 +530,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
const u8 *target_addr, *orig_addr;
const u8 *da;
u8 target_flags, ttl, flags;
u32 orig_sn, target_sn, lifetime, target_metric;
u32 orig_sn, target_sn, lifetime, target_metric = 0;
bool reply = false;
bool forward = true;
bool root_is_gate;

View File

@ -1606,7 +1606,7 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb,
* When in TCP_TIME_WAIT the sk is not a "struct sock" but
* "struct inet_timewait_sock" which is missing fields.
*/
if (sk->sk_state == TCP_TIME_WAIT) {
if (!sk_fullsock(sk) || sk->sk_state == TCP_TIME_WAIT) {
sock_gen_put(sk);
sk = NULL;
}
@ -1689,7 +1689,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
/* default: Fall through and do UID releated work */
}
sk = skb->sk;
sk = skb_to_full_sk(skb);
/*
* When in TCP_TIME_WAIT the sk is not a "struct sock" but
* "struct inet_timewait_sock" which is missing fields.

View File

@ -420,6 +420,7 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)
!strcmp(sb->s_type->name, "sysfs") ||
!strcmp(sb->s_type->name, "pstore") ||
!strcmp(sb->s_type->name, "debugfs") ||
!strcmp(sb->s_type->name, "tracefs") ||
!strcmp(sb->s_type->name, "rootfs");
}
@ -464,13 +465,6 @@ static int sb_finish_set_opts(struct super_block *sb)
if (selinux_is_sblabel_mnt(sb))
sbsec->flags |= SBLABEL_MNT;
/*
* Special handling for rootfs. Is genfs but supports
* setting SELinux context on in-core inodes.
*/
if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
sbsec->flags |= SBLABEL_MNT;
/* Initialize the root inode. */
rc = inode_doinit_with_dentry(root_inode, root);
@ -3660,6 +3654,38 @@ static int selinux_kernel_module_request(char *kmod_name)
SYSTEM__MODULE_REQUEST, &ad);
}
static int selinux_kernel_module_from_file(struct file *file)
{
struct common_audit_data ad;
struct inode_security_struct *isec;
struct file_security_struct *fsec;
struct inode *inode;
u32 sid = current_sid();
int rc;
/* init_module */
if (file == NULL)
return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
SYSTEM__MODULE_LOAD, NULL);
/* finit_module */
ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = file->f_path;
inode = file_inode(file);
isec = inode->i_security;
fsec = file->f_security;
if (sid != fsec->sid) {
rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
if (rc)
return rc;
}
return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
SYSTEM__MODULE_LOAD, &ad);
}
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
{
return current_has_perm(p, PROCESS__SETPGID);
@ -5950,6 +5976,7 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
LSM_HOOK_INIT(kernel_module_from_file, selinux_kernel_module_from_file),
LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
LSM_HOOK_INIT(task_getsid, selinux_task_getsid),

View File

@ -32,7 +32,7 @@ struct security_class_mapping secclass_map[] = {
"setsockcreate", NULL } },
{ "system",
{ "ipc_info", "syslog_read", "syslog_mod",
"syslog_console", "module_request", NULL } },
"syslog_console", "module_request", "module_load", NULL } },
{ "capability",
{ "chown", "dac_override", "dac_read_search",
"fowner", "fsetid", "kill", "setgid", "setuid", "setpcap",