I am learning android avd goldfish kernel. I have already inserted a kernel to goldfish kernel. I can hook read contacts API.
How can I tell which application calls Linux kernel?
My kernel source:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <linux/semaphore.h>
#include <linux/string.h>
#include <asm/cacheflush.h>
void **sys_call_table;
asmlinkage int (*original_call_open)(const char *, int, int);
asmlinkage int (*original_call_read)(unsigned int, char *, int);
asmlinkage int our_sys_read(unsigned int fd, char *buf, int count)
{
if (fd == 0 && count == 1)
printk("I have files being read: intercept 0x%02X", buf[0]);
return original_call_read(fd, buf, count);
}
asmlinkage int our_sys_open(const char *file, int flags, int mode)
{
/* Contacts:
* /data/data/com.android.providers.contacts/databases/contacts2.db
* Call records:
* /data/data/com.android.providers.telephony/databases/telephony.db
* SMS records:
* /data/data/com.android.providers.telephony/databases/mmssms.db
*/
char *contact ="/data/data/com.android.providers.contacts/databases/contacts2.db";
char *telephony = "/data/data/com.android.providers.telephony/databases/telephony.db";
char *sms = "/data/data/com.android.providers.telephony/databases/mmssms.db";
if (strcmp(file, contact) == 0)
printk("The application is reading phone contact records!\n");
if (strcmp(file, telephony) == 0)
printk("The application is reading the phone call records!\n");
if (strcmp(file, sms) == 0)
printk("The application is reading phone message recording!\n");
/* printk("A file was opened\n%s\n%d\n%d\n", file, flags, mode); */
return original_call_open(file, flags, mode);
}
int init_module(void)
{
sys_call_table = (void*)0xc0022f24;
original_call_open = sys_call_table[__NR_open];
original_call_read = sys_call_table[__NR_read];
sys_call_table[__NR_open] = our_sys_open;
sys_call_table[__NR_read] = our_sys_read;
return 0;
}
void cleanup_module(void)
{
/* Restore the original call */
sys_call_table[__NR_open] = original_call_open;
sys_call_table[__NR_read] = original_call_read;
}
Related
I use superpowered, I need send midi note to a controller midi.
The problem is that I saw a function send(int deviceID, unsigned char *data, int bytes);
Where in their source code say:
deviceID: Device identifier.
data: Raw MIDI data.
bytes: Number of
bytes.
I don't know the values that I need put exactly on data and bytes to work.
The raw midi could be 0x80 - 0x48 - 0x00(start of C4 note, pitch= 72, See values)
And the bytes 1001nnnn0kkkkkkk0kkkkkkk(note on event See values) for example?
Something like that:
SuperpoweredUSBMIDI::send(deviceID, reinterpret_cast(0x80 - 0x48 - 0x00), 1001nnnn0kkkkkkk0kkkkkkk);
The problem that always crash, and I can't debug or get the error for the reason that I use the mobile with otg to replicate the error.
When I find a solution, I will put it as soon as I can.
I'm newbie with markdown, sorry for any mistakes and my English grammar.
Edit: I'm using the example project that they have on GitHub for testing purposes, specifically the simpleusb project. (source)
I make a small modifications and work, but with this specifically I try with many ways and nothing. I think this simple macrochange at least could work if I insert well the values
class simpleusb.cpp:
#include <jni.h>
#include <math.h>
#include <SuperpoweredCPU.h>
#include <AndroidIO/SuperpoweredUSBAudio.h>
#include <malloc.h>
#include <pthread.h>
// Called when the application is initialized. You can initialize SuperpoweredUSBSystem
// at any time btw. Although this function is marked __unused, it's due Android Studio's
// annoying warning only. It's definitely used.
__unused jint JNI_OnLoad (
JavaVM * __unused vm,
void * __unused reserved
) {
SuperpoweredUSBSystem::initialize(NULL, NULL, NULL, NULL, NULL);
return JNI_VERSION_1_6;
}
// Called when the application is closed. You can destroy SuperpoweredUSBSystem at any time btw.
// Although this function is marked __unused, it's due Android Studio's annoying warning only.
// It's definitely used.
__unused void JNI_OnUnload (
JavaVM * __unused vm,
void * __unused reserved
) {
SuperpoweredUSBSystem::destroy();
}
// A helper structure for sine wave output.
typedef struct sineWaveOutput {
float mul;
unsigned int step;
} sineWaveOutput;
// This is called periodically for audio I/O. Audio is always 32-bit floating point,
// regardless of the bit depth preference. (SuperpoweredUSBAudioProcessingCallback)
static bool audioProcessing (
void *clientdata,
int __unused deviceID,
float *audioIO,
int numberOfSamples,
int samplerate,
int __unused numInputChannels,
int numOutputChannels
) {
// If audioIO is NULL, then it's the very last call, IO is closing.
if (!audioIO) {
// Free memory for sine wave struct.
free(clientdata);
return true;
}
sineWaveOutput *swo = (sineWaveOutput *)clientdata;
if (swo->mul == 0.0f) swo->mul = (2.0f * float(M_PI) * 300.0f) / float(samplerate);
// Output sine wave on all output channels.
for (int n = 0; n < numberOfSamples; n++) {
float v = sinf(swo->step++ * swo->mul) * 0.5f;
for (int c = 0; c < numOutputChannels; c++) *audioIO++ = v;
}
return true; // Return false for silence, true if we put audio output into audioIO.
}
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static int latestMidiCommand = -1;
static int latestMidiChannel = 0;
static int latestMidiNumber = 0;
static int latestMidiValue = 0;
// This is called when some MIDI data is coming in.
// We are doing some primitive MIDI data processing here.
static void onMidiReceived (
void * __unused clientdata,
int __unused deviceID,
unsigned char *data,
int bytes
) {
while (bytes > 0) {
if (*data > 127) {
int command = *data >> 4;
switch (command) {
case 8: // note off
case 9: // note on
case 11: // control change
pthread_mutex_lock(&mutex);
// store incoming MIDI data
latestMidiCommand = command;
latestMidiChannel = *data++ & 15;
latestMidiNumber = *data++;
latestMidiValue = *data++;
pthread_mutex_unlock(&mutex);
bytes -= 3;
break;
default:
data++;
bytes--;
}
} else {
data++;
bytes--;
}
}
}
// Beautifying the ugly Java-C++ bridge (JNI) with these macros.
#define PID com_superpowered_simpleusb_SuperpoweredUSBAudio // Java package name and class name. Don't forget to update when you copy this code.
#define MAKE_JNI_FUNCTION(r, n, p) extern "C" JNIEXPORT r JNICALL Java_ ## p ## _ ## n
#define JNI(r, n, p) MAKE_JNI_FUNCTION(r, n, p)
// This is called by the SuperpoweredUSBAudio Java object when a USB device is connected.
JNI(jint, onConnect, PID) (
JNIEnv *env,
jobject __unused obj,
jint deviceID,
jint fd,
jbyteArray rawDescriptor
) {
jbyte *rd = env->GetByteArrayElements(rawDescriptor, NULL);
int dataBytes = env->GetArrayLength(rawDescriptor);
int r = SuperpoweredUSBSystem::onConnect(deviceID, fd, (unsigned char *)rd, dataBytes);
env->ReleaseByteArrayElements(rawDescriptor, rd, JNI_ABORT);
// r is 0 if SuperpoweredUSBSystem can't do anything with the connected device.
// r & 2 is true if the device has MIDI. Start receiving events.
if (r & 2) {
SuperpoweredUSBMIDI::startIO(deviceID, NULL, onMidiReceived);
//TODO HERE IT'S THE PROBLEM: error: integer literal is too large to be represented in any integer type
SuperpoweredUSBMIDI::send(deviceID, reinterpret_cast<unsigned char *>(0x80 - 0x48 - 0x00), 100100010011100000000011);
//FINISH PROBLEM
}
// r & 1 is true if the device has audio. Start output.
if (r & 1) {
// allocate struct for sine wave oscillator
sineWaveOutput *swo = (sineWaveOutput *)malloc(sizeof(sineWaveOutput));
if (swo) {
swo->mul = 0.0f;
swo->step = 0;
SuperpoweredCPU::setSustainedPerformanceMode(true);
// Our preferred settings: 44100 Hz, 16 bits, 0 input channels, 256 output channels,
// low latency. Superpowered will set up the audio device as close as it can to these.
SuperpoweredUSBAudio::easyIO (
deviceID, // deviceID
44100, // sampling rate
16, // bits per sample
0, // numInputChannels
256, // numOutputChannels
SuperpoweredUSBLatency_Low, // latency
swo, // clientData
audioProcessing // SuperpoweredUSBAudioProcessingCallback
);
}
}
return r;
}
// This is called by the SuperpoweredUSBAudio Java object when a USB device is disconnected.
JNI(void, onDisconnect, PID) (
JNIEnv * __unused env,
jobject __unused obj,
jint deviceID
) {
SuperpoweredUSBSystem::onDisconnect(deviceID);
SuperpoweredCPU::setSustainedPerformanceMode(false);
}
#undef PID
#define PID com_superpowered_simpleusb_MainActivity
// This is called by the MainActivity Java object periodically.
JNI(jintArray, getLatestMidiMessage, PID) (
JNIEnv *env,
jobject __unused obj
) {
jintArray ints = env->NewIntArray(4);
jint *i = env->GetIntArrayElements(ints, 0);
pthread_mutex_lock(&mutex);
i[0] = latestMidiCommand;
i[1] = latestMidiChannel;
i[2] = latestMidiNumber;
i[3] = latestMidiValue;
pthread_mutex_unlock(&mutex);
env->ReleaseIntArrayElements(ints, i, 0);
return ints;
}
The other important class but I don't change on this problem, MainActivity:
#RequiresApi(api = Build.VERSION_CODES.M)
public class MainActivity extends AppCompatActivity implements SuperpoweredUSBAudioHandler {
private Handler handler;
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text);
SuperpoweredUSBAudio usbAudio = new SuperpoweredUSBAudio(getApplicationContext(), this);
usbAudio.check();
// Update UI every 40 ms.
Runnable runnable = new Runnable() {
#Override
public void run() {
int[] midi = getLatestMidiMessage();
switch (midi[0]) {
case 8: textView.setText(String.format(Locale.ENGLISH, "Note Off, CH %d, %d, %d",
midi[1] + 1, midi[2], midi[3]));
break;
case 9: textView.setText(String.format(Locale.ENGLISH, "Note On, CH %d, %d, %d",
midi[1] + 1, midi[2], midi[3]));
break;
case 11: textView.setText(String.format(Locale.ENGLISH, "Control Change, CH %d, %d, %d",
midi[1] + 1, midi[2], midi[3]));
break;
}
handler.postDelayed(this, 40);
}
};
handler = new Handler();
handler.postDelayed(runnable, 40);
/*Not look, only for testing purposes and for remember what use.
byte[] buffer = new byte[32];
int numBytes = 0;
int channel = 6; // MIDI channels 1-16 are encoded as 0-15.
buffer[numBytes++] = (byte)(0x90 + (channel - 1)); // note on
buffer[numBytes++] = (byte)60; // pitch is middle C
buffer[numBytes++] = (byte)127; // max velocity
int offset = 0;*/
}
public void onUSBAudioDeviceAttached(int deviceIdentifier) {
}
public void onUSBMIDIDeviceAttached(int deviceIdentifier) {
}
public void onUSBDeviceDetached(int deviceIdentifier) {
}
// Function implemented in the native library.
private native int[] getLatestMidiMessage();
static {
System.loadLibrary("SuperpoweredExample");
}
}
Error that I can't build app finally:
Build command failed.
Error while executing process D:\Users\ramoc\AppData\Local\Android\sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build F:\PROYECTOFIN\SuperpoweredUSBExample\simpleusb\.externalNativeBuild\cmake\debug\arm64-v8a --target SuperpoweredExample}
[1/2] Building CXX object CMakeFiles/SuperpoweredExample.dir/simpleusb.cpp.o
FAILED: D:\Users\ramoc\AppData\Local\Android\sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android --gcc-toolchain=D:/Users/ramoc/AppData/Local/Android/sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64 --sysroot=D:/Users/ramoc/AppData/Local/Android/sdk/ndk-bundle/sysroot -DSuperpoweredExample_EXPORTS -IF:/PROYECTOFIN/SuperpoweredUSBExample/simpleusb/src/main/jni/src/main/jni -IF:/PROYECTOFIN/SuperpoweredUSBExample/simpleusb/../../../Superpowered -isystem D:/Users/ramoc/AppData/Local/Android/sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include -isystem D:/Users/ramoc/AppData/Local/Android/sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/arm64-v8a/include -isystem D:/Users/ramoc/AppData/Local/Android/sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include/backward -isystem D:/Users/ramoc/AppData/Local/Android/sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -fsigned-char -IF:\PROYECTOFIN\SuperpoweredUSBExample\simpleusb\..\..\..\Superpowered -O0 -fno-limit-debug-info -fPIC -MD -MT CMakeFiles/SuperpoweredExample.dir/simpleusb.cpp.o -MF CMakeFiles\SuperpoweredExample.dir\simpleusb.cpp.o.d -o CMakeFiles/SuperpoweredExample.dir/simpleusb.cpp.o -c F:\PROYECTOFIN\SuperpoweredUSBExample\simpleusb\src\main\jni\simpleusb.cpp
F:\PROYECTOFIN\SuperpoweredUSBExample\simpleusb\src\main\jni\simpleusb.cpp:129:100: error: integer literal is too large to be represented in any integer type
SuperpoweredUSBMIDI::send(deviceID, reinterpret_cast<unsigned char *>(0x80 - 0x48 - 0x00), 100100010011100000000011);
^
F:\PROYECTOFIN\SuperpoweredUSBExample\simpleusb\src\main\jni\simpleusb.cpp:129:100: warning: implicit conversion from 'unsigned long long' to 'int' changes value from 7976667151972931595 to 887068683 [-Wconstant-conversion]
SuperpoweredUSBMIDI::send(deviceID, reinterpret_cast<unsigned char *>(0x80 - 0x48 - 0x00), 100100010011100000000011);
~~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~
1 warning and 1 error generated.
ninja: build stopped: subcommand failed.
Maybe it's for the documentation, very newbie with jni or too complex to me for now to understand 100%.
Ok, so here's what send is saying:
send(int deviceID, unsigned char *data, int bytes);
Send to deviceId a pointer to a buffer called data that has a certain number of bytes.
So when you say:
SuperpoweredUSBMIDI::send(deviceID, reinterpret_cast(0x80 - 0x48 - 0x00), 100100010011100000000011);
What you are essentially saying is "subtract these 3 numbers: 0x80 - 0x48 - 0x00", then re-interpret that number as a pointer to a buffer somewhere in memory. That buffer in memory contains 100100010011100000000011 bytes of data that I want you to read.
To fix this, we would send the data like this:
unsigned char* send_buffer[32] = {0}; // zero out buffer to use as scratch
send_buffer[0] = 0x90;
send_buffer[1] = 0x48;
send_buffer[2] = 0x00;
SuperpoweredUSBMIDI::send(deviceID, send_buffer, 3);
i thought midi had a check sum value (byte) appended to the sequence - is that done in your code or in the library code?
the message should be an array of unsigned char and pass the address of the array (name)
well that's what id have done in C when I was programming midi.
The problem is "insmod success", but seems the entry function "demo_init()" is not been executed. lsmod shows the module loaded successfully and no errors or warnings. However, I can't see "Hello, World!" after dmesg, and there is no device node "/dev/demo_device" and there is no class "/sys/class/demo_class". I'm not able to figure it out.
Someone could help me, thanks.
The kernel version is 3.10.86.
The system Android.
This is my code:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
int major;
static struct class *demo_class;
static struct device *demo_device;
static int demo_open(struct inode * inode, struct file * filp)
{
printk(KERN_ALERT "demo_open\n");
return 0;
}
static int demo_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)
{
printk(KERN_ALERT "demo_write\n");
return 0;
}
static const struct file_operations demo_fops = {
.owner = THIS_MODULE,
.open = demo_open,
.write = demo_write,
};
static int __init demo_init(void) {
printk(KERN_ALERT "Hello, World!\n");
major = register_chrdev(0, "demo_drv", &demo_fops);
demo_class = class_create(THIS_MODULE, "demo_class");
demo_device = device_create(demo_class, NULL, MKDEV(major, 0), NULL, "demo_device");
return 0;
}
static void __exit demo_exit(void) {
printk(KERN_ALERT "Goodbye, World!\n");
unregister_chrdev(major, "demo_drv");
device_unregister(demo_device);
class_destroy(demo_class);
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_VERSION("0.01");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("A simple example Linux module.");
/android/kernel/arch/arm/mm/rodata.c:91:4: warning: format '%lx' expects argument of type 'long unsigned int', but argument 4 has type 'pmd_t' [-Wformat]
what to end this warning
/*
* linux/arch/arm/mm/rodata.c
*
* Copyright (C) 2011 Google, Inc.
*
* Author: Colin Cross <ccross#android.com>
*
* Based on x86 implementation in arch/x86/mm/init_32.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <asm/cache.h>
#include <asm/pgtable.h>
#include <asm/rodata.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
#include "mm.h"
static int kernel_set_to_readonly __read_mostly;
#ifdef CONFIG_DEBUG_RODATA_TEST
static const int rodata_test_data = 0xC3;
static noinline void rodata_test(void)
{
int result;
pr_info("%s: attempting to write to read-only section:\n", __func__);
if (*(volatile int *)&rodata_test_data != 0xC3) {
pr_err("read only data changed before test\n");
return;
}
/*
* Attempt to to write to rodata_test_data, trapping the expected
* data abort. If the trap executed, result will be 1. If it didn't,
* result will be 0xFF.
*/
asm volatile(
"0: str %[zero], [%[rodata_test_data]]\n"
" mov %[result], #0xFF\n"
" b 2f\n"
"1: mov %[result], #1\n"
"2:\n"
/* Exception fixup - if store at label 0 faults, jumps to 1 */
".pushsection __ex_table, \"a\"\n"
" .long 0b, 1b\n"
".popsection\n"
: [result] "=r" (result)
: [rodata_test_data] "r" (&rodata_test_data), [zero] "r" (0)
: "memory"
);
if (result == 1)
pr_info("write to read-only section trapped, success\n");
else
pr_err("write to read-only section NOT trapped, test failed\n");
if (*(volatile int *)&rodata_test_data != 0xC3)
pr_err("read only data changed during write\n");
}
#else
static inline void rodata_test(void) { }
#endif
static int set_page_attributes(unsigned long virt, int numpages,
pte_t (*f)(pte_t))
{
pmd_t *pmd;
pte_t *pte;
unsigned long start = virt;
unsigned long end = virt + (numpages << PAGE_SHIFT);
unsigned long pmd_end;
while (virt < end) {
pmd = pmd_off_k(virt);
pmd_end = min(ALIGN(virt + 1, PMD_SIZE), end);
if ((pmd_val(*pmd) & PMD_TYPE_MASK) != PMD_TYPE_TABLE) {
pr_err("%s: pmd %p=%08lx for %08lx not page table\n",
__func__, pmd, pmd_val(*pmd), virt);
virt = pmd_end;
continue;
}
while (virt < pmd_end) {
pte = pte_offset_kernel(pmd, virt);
set_pte_ext(pte, f(*pte), 0);
virt += PAGE_SIZE;
}
}
flush_tlb_kernel_range(start, end);
return 0;
}
int set_memory_ro(unsigned long virt, int numpages)
{
return set_page_attributes(virt, numpages, pte_wrprotect);
}
EXPORT_SYMBOL(set_memory_ro);
int set_memory_rw(unsigned long virt, int numpages)
{
return set_page_attributes(virt, numpages, pte_mkwrite);
}
EXPORT_SYMBOL(set_memory_rw);
void set_kernel_text_rw(void)
{
unsigned long start = PAGE_ALIGN((unsigned long)_text);
unsigned long size = PAGE_ALIGN((unsigned long)__end_rodata) - start;
if (!kernel_set_to_readonly)
return;
pr_debug("Set kernel text: %lx - %lx to read-write\n",
start, start + size);
set_memory_rw(start, size >> PAGE_SHIFT);
}
void set_kernel_text_ro(void)
{
unsigned long start = PAGE_ALIGN((unsigned long)_text);
unsigned long size = PAGE_ALIGN((unsigned long)__end_rodata) - start;
if (!kernel_set_to_readonly)
return;
pr_info_once("Write protecting the kernel text section %lx - %lx\n",
start, start + size);
pr_debug("Set kernel text: %lx - %lx to read only\n",
start, start + size);
set_memory_ro(start, size >> PAGE_SHIFT);
}
void mark_rodata_ro(void)
{
kernel_set_to_readonly = 1;
set_kernel_text_ro();
rodata_test();
}
what to do to end this warning , sorry i am not a programmer but i am thinking to be one :D
just removed the L
to be changed to:
pr_err("%s: pmd %p=%08x for %08lx not page table\n",
and it WORKS.
thanks #R_Kapp
I want to implements kernel communicate with user space,Here is my code:
#include <sys/socket.h>
#include <linux/netlink.h>
#include <stddef.h>
#define NETLINK_USER 16
#define MAX_PAYLOAD 1024 /* maximum payload size*/
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
int sock_fd;
struct msghdr msg;
void main()
{
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
printf("%d\n",sock_fd);
if (sock_fd < 0)
return -1;
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid(); /* self pid */
printf("%d\n",getpid());
.....
When I set NETLINK_USER = 17,18 or something else, then I exec this code :
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER);
it show sock_fd return -1, so it must set NETLINK_USER = 16, I want know why?
And I have another question: Here is my kernel code:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <linux/semaphore.h>
#include <asm/cacheflush.h>
#include <linux/string.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <stddef.h>
#define NETLINK_USER 16
struct sock *nl_sk = NULL;
void **sys_call_table;
asmlinkage int (*original_call_open) (const char*, int, int);
asmlinkage int (*original_call_read) (unsigned int, char*, int);
asmlinkage long (*sys_openat) (int, const char*, int, int);
asmlinkage long our_openat(int dfd, const char *filename, int flags, int mode){
printk("%s\n",filename);
return sys_openat(dfd,filename,flags,mode);
}
void hello_nl_recv_msg(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
int pid;
struct sk_buff *skb_out;
int msg_size;
char *msg = "Hello from kernel";
int res;
printk(KERN_INFO "Entering: %s\n", __FUNCTION__);
msg_size = strlen(msg);
nlh = (struct nlmsghdr *)skb->data;
printk(KERN_INFO "Netlink received msg payload:%s\n", (char *)nlmsg_data(nlh));
pid = nlh->nlmsg_pid; //pid of sending process
skb_out = nlmsg_new(msg_size, 0);
if (!skb_out)
{
printk(KERN_ERR "Failed to allocate new skb\n");
return;
}
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
NETLINK_CB(skb_out).dst_group = 0; //not in mcast group
strncpy(nlmsg_data(nlh), msg, msg_size);
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (res < 0)
printk(KERN_INFO "Error while sending bak to user\n");
}
int init_module()
{
printk("Entering: %s\n", __FUNCTION__);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, hello_nl_recv_msg, NULL, THIS_MODULE);
// printk("%s",nl_sk);
// nl_sk = netlink_kernel_create(NETLINK_USER, input);
if (!nl_sk)
{
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
void cleanup_module()
{
// Restore the original call
sys_call_table[__NR_open] = original_call_open;
sys_call_table[__NR_read] = original_call_read;
sys_call_table[__NR_openat] = sys_openat;
printk(KERN_INFO "exiting hello module\n");
netlink_kernel_release(nl_sk);
}
//MODULE_LICENSE("GPL");
//module_init(init_module);
//module_exit(cleanup_module);
I found if I set NETLINK_USER = 16, when I insert kernel, the avd will stop running, but if I set NETLINK_USER = 31,28 or something else the avd will run normally,I want to know why it will like this?
At last, I think the function hello_nl_recv_msg haven't exec, I don't know why.
I am trying to run a simple IOCTL example on Android. I am using kernel 2.6 and ICS. The module is properly registered/unregistered (insmod/rmmod). However, every time a try to execute ./user_app on the emulator, I always get
error: first ioctl: Not a typewriter
error: second ioctl: Not a typewriter
message: `�
This is clearly a ENOTTY. I debugged the application, and no fops procedure (device_ioctl, read_ioctl and write_ioctl) is being executed.
I would like to know if there is any restriction with the usage/implementation of IOCTL on Android. Thank you very much in advance.
--Raul
Here is the code:
module.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define MY_MACIG 'G'
#define READ_IOCTL _IOR(MY_MACIG, 0, int)
#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)
int main(){
char buf[200];
int fd = -1;
if ((fd = open("/data/local/afile.txt", O_RDWR)) < 0) {
perror("open");
return -1;
}
if(ioctl(fd, WRITE_IOCTL, "hello world") < 0)
perror("first ioctl");
if(ioctl(fd, READ_IOCTL, buf) < 0)
perror("second ioctl");
printf("message: %s\n", buf);
return 0;
}
user_app.c
#include <stdio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#define MY_MACIG 'G'
#define READ_IOCTL _IOR(MY_MACIG, 0, int)
#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)
static char msg[200];
static ssize_t device_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset)
{
...
}
static ssize_t device_write(struct file *filp, const char __user *buff, size_t len, loff_t *off)
{
...
}
char buf[200];
int device_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) {
int len = 200;
switch(cmd) {
case READ_IOCTL:
...
break;
case WRITE_IOCTL:
...
break;
default:
return -ENOTTY;
}
return len;
}
static struct file_operations fops = {
.read = device_read,
.write = device_write,
.unlocked_ioctl = device_ioctl,
};
static int __init example_module_init(void)
{
printk("registering module");
return 0;
}
static void __exit example_module_exit(void)
{
printk("unregistering module");
}
module_init(example_module_init);
module_exit(example_module_exit);
MODULE_LICENSE("GPL");
It this the whole code that you've posted? You don't register a char device when initializing a module, so this can't work.
Also, be carefull when assigning IOCTLS numbers. When using reserved IOCTL on a wrong file, you will get ENOTTY. Consult this to make sure you don't have conflicts.
Read more about char drivers here.