Why does this code works well? It changes the Constant storage area string; - linux

this is a simple linux kernel module code to reverse a string which should Oops after insmod,but it works well,why?
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static char *words = "words";
static int __init words_init(void)
{
printk(KERN_INFO "debug info\n");
int len = strlen(words);
int k;
for ( k = 0; k < len/2; k++ )
{
printk("the value of k %d\n",k);
char a = words[k];
words[k]= words[len-1-k];
words[len-1-k]=a;
}
printk(KERN_INFO "words is %s\n", words);
return 0;
}
static void __exit words_exit(void)
{
printk(KERN_INFO "words exit.\n");
}
module_init(words_init);
module_exit(words_exit);
module_param(words, charp, S_IRUGO);
MODULE_LICENSE("GPL");

static != const.
static in your example means "only visible in the current file". See What does "static" mean?
const just means "the code which can see this declaration isn't supposed to change the variable". But in certain cases, you can still create a non-const pointer to the same address and modify the contents.
Space removal from a String - In Place C style with Pointers suggests that writing to the string value shouldn't be possible.
Since static is the only difference between your code and that of the question, I looked further and found this: Global initialized variables declared as "const" go to text segment, while those declared "Static" go to data segment. Why?
Try static const char *word, that should do the trick.

Haha!,I get the answer from the linux kernel source code by myself;When you use the insmod,it will call the init_moudle,load_module,strndup_usr then memdup_usr function;the memdup_usr function will use kmalloc_track_caller to alloc memery from slab and then use the copy_from_usr to copy the module paragram into kernel;this mean the linux kernel module paragram store in heap,not in the constant storage area!! So we can change it's content!

Related

Is there a way to find the file names of files mapped to the virtual memory area of a process in the linux kernel?

Been working on a project for a few weeks now and I've hit a pretty significant roadblock and I was hoping somebody here might be able to offer some guidance.
All I need to do is write a system call that reports statistics of a process’s virtual address space when called. Those statistics, according to the assignment criteria, need to include the size of the process’s virtual address space, each virtual memory area’s access permissions, and the names of files mapped to these virtual memory areas.
The first two I have working, the last appears to not be possible, at least from what my research and attempts so far have turned up. I've isolated it down to accessing the vm_file struct within the vm_area_struct of the process and using that to get to the f_path, but past that I'm still stuck on how to get from there to a format that can actually be put into a printk statement, and everything I've tried hasn't output anything when I finally get the kernel recompiled.
Here's where the code sits at the moment. Am I even on the right track?
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm_types.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/path.h>
#include <linux/dcache.h>
asmlinkage int sys_project3a1(unsigned int processID)
{
struct task_struct *task;
for_each_process(task)
{
if (task->pid == processID)
{
unsigned long virtualAddressSpace = 0;
struct vm_area_struct *vmlist;
printk("Process ID: %d", task->pid);
for (vmlist = task->mm->mmap; vmlist!=NULL; vmlist=vmlist->vm_next)
{
unsigned long space = vmlist->vm_end - vmlist->vm_start;
char *tmp;
char *pathname;
struct file *file;
struct path *path;
printk("Process Access Permissions: %lu", (unsigned long)(vmlist->vm_page_prot.pgprot));
file = vmlist->vm_file;
path = &file->f_path;
path_get(path);
tmp = (char *)__get_free_page(GFP_TEMPORARY);
pathname = d_path(path, tmp, PAGE_SIZE);
printk("Path Name: %s", pathname);
free_page((unsigned long)tmp);
virtualAddressSpace += space;
}
printk("Process Virtual Address Space: %lu", virtualAddressSpace);
}
}
return 1;
}
I was in a similar situation and had to find this on my own. Hope others who come here benefit from my answer.
So I am assuming you want the values corresponding to "Mapping" column of a pmap command ouput. The following works for me(tried on v4.6.4):
char filename[50];
if(vmlist->vm_file){
strcpy(filename, vmlist->vm_file->f_path.dentry->d_iname);
}
else{ // implies an anonymous mapping i.e. not file backup'ed
strcpy(filename, "[ anon ]");
}
After getting to the path, follow it's dentry field and then d_iname which is the mapped file's name. Doesn't look quite pretty, but does the job.
struct vm_area_struct *vas;
vas->vm_file->f_path.dentry->d_name.name

How to change the name of a haskell process under linux

I am trying to change the name of a running process under linux. In C, I would just modify argv[0] in-place, but how can I do that from haskell? I noticed that ghc has a primitive called getProgArgv:
foreign import ccall unsafe "getProgArgv"
getProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
but I tried with that and it didn't work. Also, I am aware of prctl(PR_SET_NAME,"...") but that only changes the current thread's name, and most tools (such as ps and htop) do not use that name.
Ok, so I came up with an ugly hack that seems to work. It based on a idea borrowed from here. We have to use an auxiliary c file:
#include <string.h>
#include <sys/prctl.h>
char *argv0 = 0;
static void capture_argv0(int argc, char *argv[]) {
argv0 = argv[0];
}
__attribute__((section(".init_array"))) void (*p_capture_argv0)(int, char*[]) = &capture_argv0;
void set_prog_name(char *name) {
if (!argv0) return;
size_t len = strlen(argv0);
strncpy(argv0, name, len);
prctl(PR_SET_NAME, name);
}
This relies on the section(".init_array") attribute that tells gcc to register capture_argv0 as an initialization function. This means that it will be executed before main. We use it to make a copy of the argv[0] pointer and store it as a global variable. Now we can call set_prog_name from haskell.

Can't use memcpy on char * attribute as destination - visual c++

I have the following piece of code in appPOSWebDlg.cpp:
#include "stdafx.h"
#include "afx.h"
#include <stdlib.h>
#include <Ras.h>
...
//Attribute
char *site;
...
// Method
int readFile() {
char * aux;
int result;
result = readParameter(hFile, aux);
if (result == 0) {
memcpy(site, aux, 256);
} else {
return 1;
}
return 0;
}
But the program stops at the memcpy line and I'm not sure why. After debugging, I can confirm that the aux parameter is being assigned correctly with the value expected. Furthermore, I even used the memcpy inside the readParameter method to assign it and had no problem. So why can't I assign that value to attribute site using the same method?
Your "site" pointer is invalid. You've defined it as a pointer, but, not allocated any space for it, so, your copy command is overlaying some code. You'll need to allocated the pointer correctly by performing a "new" and a "delete" when you are done.

Why I can't use global float constants in device code? [duplicate]

I am using CUDA 5.0. I noticed that the compiler will allow me to use host-declared int constants within kernels. However, it refuses to compile any kernels that use host-declared float constants. Does anyone know the reason for this seeming discrepancy?
For example, the following code runs just fine as is, but it will not compile if the final line in the kernel is uncommented.
#include <cstdio>
#include <cuda_runtime.h>
static int __constant__ DEV_INT_CONSTANT = 1;
static float __constant__ DEV_FLOAT_CONSTANT = 2.0f;
static int const HST_INT_CONSTANT = 3;
static float const HST_FLOAT_CONSTANT = 4.0f;
__global__ void uselessKernel(float * val)
{
*val = 0.0f;
// Use device int and float constants
*val += DEV_INT_CONSTANT;
*val += DEV_FLOAT_CONSTANT;
// Use host int and float constants
*val += HST_INT_CONSTANT;
//*val += HST_FLOAT_CONSTANT; // won't compile if uncommented
}
int main(void)
{
float * d_val;
cudaMalloc((void **)&d_val, sizeof(float));
uselessKernel<<<1, 1>>>(d_val);
cudaFree(d_val);
}
Adding a const number in the device code is OK, but adding a number stored on the host memory in the device code is NOT.
Every reference of the static const int in your code can be replaced with the value 3 by the compiler/optimizer when the addr of that variable is never referenced. In this case, it is like #define HST_INT_CONSTANT 3, and no host memory is allocated for this variable.
But for float var, the host memory is always allocated even it is of static const float. Since the kernel can not access the host memory directly, your code with static const float won't be compiled.
For C/C++, int can be optimized more aggressively than float.
You code runs when the comment is ON can be seen as a bug of CUDA C I think. The static const int is a host side thing, and should not be accessible to the device directly.

atoi on a character array with lots of integers

I have a code in which the character array is populated by integers (converted to char arrays), and read by another function which reconverts it back to integers. I have used the following function to get the conversion to char array:
char data[64];
int a = 10;
std::string str = boost::lexical_cast<std::string>(a);
memcpy(data + 8*k,str.c_str(),sizeof(str.c_str())); //k varies from 0 to 7
and the reconversion back to characters is done using:
char temp[8];
memcpy(temp,data+8*k,8);
int a = atoi(temp);
This works fine in general, but when I try to do it as part of a project involving qt (ver 4.7), it compiles fine and gives me segmentation faults when it tries to read using memcpy(). Note that the segmentation fault happens only while in the reading loop and not while writing data. I dont know why this happens, but I want to get it done by any method.
So, are there any other other functions which I can use which can take in the character array, the first bit and the last bit and convert it into the integer. Then I wouldnt have to use memcpy() at all. What I am trying to do is something like this:
new_atoi(data,8*k,8*(k+1)); // k varies from 0 to 7
Thanks in advance.
You are copying only a 4 characters (dependent on your system's pointer width). This will leave numbers of 4+ characters non-null terminated, leading to runaway strings in the input to atoi
sizeof(str.c_str()) //i.e. sizeof(char*) = 4 (32 bit systems)
should be
str.length() + 1
Or the characters will not be nullterminated
STL Only:
make_testdata(): see all the way down
Why don't you use streams...?
#include <sstream>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
int main()
{
std::vector<int> data = make_testdata();
std::ostringstream oss;
std::copy(data.begin(), data.end(), std::ostream_iterator<int>(oss, "\t"));
std::stringstream iss(oss.str());
std::vector<int> clone;
std::copy(std::istream_iterator<int>(iss), std::istream_iterator<int>(),
std::back_inserter(clone));
//verify that clone now contains the original random data:
//bool ok = std::equal(data.begin(), data.end(), clone.begin());
return 0;
}
You could do it a lot faster in plain C with atoi/itoa and some tweaks, but I reckon you should be using binary transmission (see Boost Spirit Karma and protobuf for good libraries) if you need the speed.
Boost Karma/Qi:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
namespace qi=::boost::spirit::qi;
namespace karma=::boost::spirit::karma;
static const char delimiter = '\0';
int main()
{
std::vector<int> data = make_testdata();
std::string astext;
// astext.reserve(3 * sizeof(data[0]) * data.size()); // heuristic pre-alloc
std::back_insert_iterator<std::string> out(astext);
{
using namespace karma;
generate(out, delimit(delimiter) [ *int_ ], data);
// generate_delimited(out, *int_, delimiter, data); // equivalent
// generate(out, int_ % delimiter, data); // somehow much slower!
}
std::string::const_iterator begin(astext.begin()), end(astext.end());
std::vector<int> clone;
qi::parse(begin, end, qi::int_ % delimiter, clone);
//verify that clone now contains the original random data:
//bool ok = std::equal(data.begin(), data.end(), clone.begin());
return 0;
}
If you wanted to do architecture independent binary serialization instead, you'd use this tiny adaptation making things a zillion times faster (see benchmark below...):
karma::generate(out, *karma::big_dword, data);
// ...
qi::parse(begin, end, *qi::big_dword, clone);
Boost Serialization
The best performance can be reached when using Boost Serialization in binary mode:
#include <sstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/vector.hpp>
int main()
{
std::vector<int> data = make_testdata();
std::stringstream ss;
{
boost::archive::binary_oarchive oa(ss);
oa << data;
}
std::vector<int> clone;
{
boost::archive::binary_iarchive ia(ss);
ia >> clone;
}
//verify that clone now contains the original random data:
//bool ok = std::equal(data.begin(), data.end(), clone.begin());
return 0;
}
Testdata
(common to all versions above)
#include <boost/random.hpp>
// generates a deterministic pseudo-random vector of 32Mio ints
std::vector<int> make_testdata()
{
std::vector<int> testdata;
testdata.resize(2 << 24);
std::generate(testdata.begin(), testdata.end(), boost::mt19937(0));
return testdata;
}
Benchmarks
I benchmarked it by
using input data of 2<<24 (33554432) random integers
not displaying output (we don't want to measure the scrolling performance of our terminal)
the rough timings were
STL only version isn't too bad actually at 12.6s
Karma/Qi text version ran in 18s 5.1s, thanks to Arlen's hint at generate_delimited :)
Karma/Qi binary version (big_dword) in only 1.4s (roughly 12x 3-4x as fast)
Boost Serialization takes the cake with around 0.8s (or when subsituting text archives instead of binaries, around 13s)
There is absolutely no reason for the Karma/Qi text version to be any slower than the STL version. I improved #sehe implementation of the Karma/Qi text version to reflect that claim.
The following Boost Karma/Qi text version is more than twice as fast as the STL version:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/random.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
namespace ascii = boost::spirit::ascii;
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace phoenix = boost::phoenix;
template <typename OutputIterator>
void generate_numbers(OutputIterator& sink, const std::vector<int>& v){
using karma::int_;
using karma::generate_delimited;
using ascii::space;
generate_delimited(sink, *int_, space, v);
}
template <typename Iterator>
void parse_numbers(Iterator first, Iterator last, std::vector<int>& v){
using qi::int_;
using qi::phrase_parse;
using ascii::space;
using qi::_1;
using phoenix::push_back;
using phoenix::ref;
phrase_parse(first, last, *int_[push_back(ref(v), _1)], space);
}
int main(int argc, char* argv[]){
static boost::mt19937 rng(0); // make test deterministic
std::vector<int> data;
data.resize(2 << 24);
std::generate(data.begin(), data.end(), rng);
std::string astext;
std::back_insert_iterator<std::string> out(astext);
generate_numbers(out, data);
//std::cout << astext << std::endl;
std::string::const_iterator begin(astext.begin()), end(astext.end());
std::vector<int> clone;
parse_numbers(begin, end, clone);
//verify that clone now contains the original random data:
//std::copy(clone.begin(), clone.end(), std::ostream_iterator<int>(std::cout, ","));
return 0;
}

Resources