mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 22:52:35 +02:00
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:
commit
cf5ba83bb2
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -104,8 +104,6 @@ source "drivers/memstick/Kconfig"
|
|||
|
||||
source "drivers/leds/Kconfig"
|
||||
|
||||
source "drivers/switch/Kconfig"
|
||||
|
||||
source "drivers/accessibility/Kconfig"
|
||||
|
||||
source "drivers/infiniband/Kconfig"
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# Switch Class Driver
|
||||
obj-$(CONFIG_SWITCH) += switch_class.o
|
||||
obj-$(CONFIG_SWITCH_GPIO) += switch_gpio.o
|
||||
|
||||
|
|
@ -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");
|
||||
|
|
@ -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");
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
43
mm/vmscan.c
43
mm/vmscan.c
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -77,4 +77,3 @@ endif
|
|||
ifneq ($(CONFIG_NET_L3_MASTER_DEV),)
|
||||
obj-y += l3mdev/
|
||||
endif
|
||||
obj-$(CONFIG_NET_ACTIVITY_STATS) += activity_stats.o
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
133
net/ipv4/tcp.c
133
net/ipv4/tcp.c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user