Permission denied while accessing /proc/<pid>/exe - linux

I am having trouble accessing the file in /proc filesystem
My process once started writes in a log file .My process was stopped and when i checked the logfile to see where it encountered the problem and found "permission denied".
it goes to the /proc directory ,fetches PID via getPID() and fires open() using O_RDONLY to read /proc/<pid>/exe
but after firing i get an error "Permission denied".
I did some research and found that kernel enforces some restrictions while accessing certain files in/proc ,but i have 20 process all accessing the same /proc/<pid>/exe ,but only one facing this problem ..
CHAR fn[100];
159 CHAR args[500];
160 CHAR ProgName[50];
161 CHAR *arr[6];
162 CHAR *buf;
163 CHAR ProcessId[10];
164 static int count_try = 0;
165
166
167 memset(fn,0,100);
168 memset(ProcessId,0,10);
169 sprintf (ProcessId,"%d",Pid);
170 strcpy(fn, "/proc/");
171 strcat(fn, ProcessId);
172 //strcat(fn, "/elf_prpsinfo");
173 strcat(fn, "/exe");
174
175 if ((psp = open(fn, O_RDONLY)) == -1)
176 {
177 perror("GetProgName:ps open::");
178 exit(ERROR);
179 }

Related

First requests not sending in the start of the goroutine func

i am running goroutines in my code. say, if i set my threads to 50, it will not run the first 49 requests, but it will run the 50th request and continue with the rest. i am not really sure how to describe the issue i am having, and it gives no errors. this has only happened while using fasthttp, and works fine with net/http. could it be an issue with fasthttp? (this is not my whole code, just the area where i think the issues are occurring)
threads := 50
var Lock sync.Mutex
semaphore := make(chan bool, threads)
for len(userArray) != 0 {
semaphore <- true
go func() {
Lock.Lock()
var values []byte
defer func() { <-semaphore }()
fmt.Println(len(userArray))
if len(userArray) == 0 {
return
}
values, _ = json.Marshal(userArray[0])
currentArray := userArray[0]
userArray = userArray[1:]
client := &fasthttp.Client{
Dial: fasthttpproxy.FasthttpHTTPDialerTimeout(proxy, time.Second * 5),
}
time.Sleep(1 * time.Nanosecond)
Lock.Unlock()
this is the output i get (the numbers are the amount of requests left)
200
199
198
197
196
195
194
193
192
191
190
189
188
187
186
185
184
183
182
181
180
179
178
177
176
175
174
173
172
171
170
169
168
167
166
165
164
163
162
161
160
159
158
157
156
155
154
153
152
151
(10 lines of output from req 151)
150
(10 lines of output from req 150)
cont.
sorry if my explanation is confusing, i honestly don't know how to explain this error
I think the problem is with the scoping of the variables. In order to represent the queueing, I'd have a pool of parallel worker threads that all pull from the same channel and then wait for them using a waitgroup.
The exact code might need to be adapted as I don't have a go compiler at hand, but the idea is like this:
threads := 50
queueSize := 100 // trying to add more into the queue will blocke
semaphore := make(chan bool, threads)
jobQueue := make(chan MyItemType, queueSize)
var wg sync.WaitGroup
func processQueue(jobQueue <- chan MyItemType) {
defer wg.Done()
for item := range jobQueue {
values, _ = json.Marshal(item) // doesn't seem to be used?
client := &fasthttp.Client{
Dial: fasthttpproxy.FasthttpHTTPDialerTimeout(proxy, time.Second * 5),
}
}
}
for i := 0; i < threads; i++ {
wg.Add(1)
go processQueue(jobQueue)
}
close(jobQueue)
wg.Wait()
Now you can put items into jobQueue and they will be processed by one of these threads.

A thread who is spinning and trying to get the spinlock can't be preempted?

When a thread on Linux is spinning and trying to get the spinlock, Is there no chance this thread can be preempted?
EDIT:
I just want to make sure some thing. On a "UP" system, and there is no interrupt handler will access this spinlock. If the thread who is spinning and trying to get the spinlock can be preempted, I think in this case, the critical section which spinlock protects can call sleep, since the thread holding spinlock can be re-scheduled back to CPU.
No it cannot be preempted: see the code (taken from linux sources) http://lxr.free-electrons.com/source/include/linux/spinlock_api_smp.h?v=2.6.32#L241
241 static inline unsigned long __spin_lock_irqsave(spinlock_t *lock)
242 {
243 unsigned long flags;
244
245 local_irq_save(flags);
246 preempt_disable();
247 spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
248 /*
249 * On lockdep we dont want the hand-coded irq-enable of
250 * _raw_spin_lock_flags() code, because lockdep assumes
251 * that interrupts are not re-enabled during lock-acquire:
252 */
253 #ifdef CONFIG_LOCKDEP
254 LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock);
255 #else
256 _raw_spin_lock_flags(lock, &flags);
257 #endif
258 return flags;
259 }
260
[...]
349 static inline void __spin_unlock(spinlock_t *lock)
350 {
351 spin_release(&lock->dep_map, 1, _RET_IP_);
352 _raw_spin_unlock(lock);
353 preempt_enable();
354 }
see lines 246 and 353
By the way It is generally a bad idea to sleep while holding a lock (spinlock or not)

Using DMA API in linux kernel but channel is never available

I am trying to use dmatest.c to test DMA in intel xeon server and regular laptop with i7 processor. It is never been able to get a channel - I found this out by debugging the dmatest.c itself. Line 854 below is always executed (I put my own printk there).
Is there anything I should do to get this API to work before executing (such as dma modules or anything?)
Or, do I use wrong API set?
On the Xeon server, I did research and it has ioatdma.ko module that can be loaded.
modprobe ioatdma
and some files available at /sys/class/dma after that, such as dma0channel0, dma1channel0 .... etc
However, running dmatest code, it still can't get any channel.
Any help or hint is appreciated.
836 static void request_channels(struct dmatest_info *info,
837 enum dma_transaction_type type)
838 {
839 dma_cap_mask_t mask;
840
841 dma_cap_zero(mask);
842 dma_cap_set(type, mask);
843 for (;;) {
844 struct dmatest_params *params = &info->params;
845 struct dma_chan *chan;
846
847 chan = dma_request_channel(mask, filter, params);
848 if (chan) {
849 if (dmatest_add_channel(info, chan)) {
850 dma_release_channel(chan);
851 break; /* add_channel failed, punt */
852 }
853 } else
854 break; /* no more channels available */
The test commands that I used (following dmatest.txt document in kernel doc):
% echo dma0chan0 > /sys/kernel/debug/dmatest/channel
% echo 2000 > /sys/kernel/debug/dmatest/timeout
% echo 1 > /sys/kernel/debug/dmatest/iterations
% echo 1 > /sys/kernel/debug/dmatest/run

Why doesn't fill the PTE entry in page fault for vmalloc on ARM Linux Kernel?

When page fault happens on VMALLOC_START~VMALLOC_END, why do_translation_fault does not fill Page table entry and just fill PG, PUD and PMD?
Corresponding source code #do_translation_fault in arch/arm/mm/fault.c:
414 static int __kprobes
415 do_translation_fault(unsigned long addr, unsigned int fsr,
416 struct pt_regs *regs)
417 {
418 unsigned int index;
419 pgd_t *pgd, *pgd_k;
420 pud_t *pud, *pud_k;
421 pmd_t *pmd, *pmd_k;
422
423 if (addr < TASK_SIZE)
424 return do_page_fault(addr, fsr, regs);
425
426 if (user_mode(regs))
427 goto bad_area;
428
429 index = pgd_index(addr);
430
431 /*
432 * FIXME: CP15 C1 is write only on ARMv3 architectures.
433 */
434 pgd = cpu_get_pgd() + index;
435 pgd_k = init_mm.pgd + index;
436
437 if (pgd_none(*pgd_k))
438 goto bad_area;
439 if (!pgd_present(*pgd))
440 set_pgd(pgd, *pgd_k);
441
442 pud = pud_offset(pgd, addr);
443 pud_k = pud_offset(pgd_k, addr);
444
445 if (pud_none(*pud_k))
446 goto bad_area;
447 if (!pud_present(*pud))
448 set_pud(pud, *pud_k);
449
450 pmd = pmd_offset(pud, addr);
451 pmd_k = pmd_offset(pud_k, addr);
452
453 #ifdef CONFIG_ARM_LPAE
454 /*
455 * Only one hardware entry per PMD with LPAE.
456 */
457 index = 0;
458 #else
459 /*
460 * On ARM one Linux PGD entry contains two hardware entries (see page
461 * tables layout in pgtable.h). We normally guarantee that we always
462 * fill both L1 entries. But create_mapping() doesn't follow the rule.
463 * It can create inidividual L1 entries, so here we have to call
464 * pmd_none() check for the entry really corresponded to address, not
465 * for the first of pair.
466 */
467 index = (addr >> SECTION_SHIFT) & 1;
468 #endif
469 if (pmd_none(pmd_k[index]))
470 goto bad_area;
471
472 copy_pmd(pmd, pmd_k);
473 return 0;
474
475 bad_area:
476 do_bad_area(addr, fsr, regs);
477 return 0;
478 }
This range is reserved for kernel memory, allocated using vmalloc.
Kernel memory is normally accessed when IRQs (soft or hard) are disabled, and page faults can't be handled.
The vmalloc function takes care to create the mapping in advance, so there will be no fault on access.
If there was a fault, it's because the access is to memory which wasn't allocated (or was freed), so it can't be handled.

Any good guides on using PTRACE_SYSEMU?

Does anyone have any good explanations, tutorials, books, or guides on the use of PTRACE_SYSEMU?
What I found interesting:
Example Implementation for ptrace
Playing with ptrace, Part I - LinuxJournal.com
Playing with ptrace, Part II - LinuxJournal.com
And programming library that makes using ptrace easier :
PinkTrace - ptrace() wrapper library.
For pinktrace there are examples, sydbox sources are example of complex pinktrace usecase. In general, I've found author as good person to contact about using and testing pinktrace.
There is small test from linux kernel sources which uses PTRACE_SYSEMU:
http://code.metager.de/source/xref/linux/stable/tools/testing/selftests/x86/ptrace_syscall.c
or http://lxr.free-electrons.com/source/tools/testing/selftests/x86/ptrace_syscall.c
186 struct user_regs_struct regs;
187
188 printf("[RUN]\tSYSEMU\n");
189 if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
190 err(1, "PTRACE_SYSCALL");
191 wait_trap(chld);
192
193 if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
194 err(1, "PTRACE_GETREGS");
195
196 if (regs.user_syscall_nr != SYS_gettid ||
197 regs.user_arg0 != 10 || regs.user_arg1 != 11 ||
198 regs.user_arg2 != 12 || regs.user_arg3 != 13 ||
199 regs.user_arg4 != 14 || regs.user_arg5 != 15) {
200 printf("[FAIL]\tInitial args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", (unsigned long)regs.user_syscall_nr, (unsigned long)regs.user_arg0, (unsigned long)regs.user_arg1, (unsigned long)regs.user_arg2, (unsigned long)regs.user_arg3, (unsigned long)regs.user_arg4, (unsigned long)regs.user_arg5);
201 nerrs++;
202 } else {
203 printf("[OK]\tInitial nr and args are correct\n");
204 }
205
206 printf("[RUN]\tRestart the syscall (ip = 0x%lx)\n",
207 (unsigned long)regs.user_ip);
208
209 /*
210 * This does exactly what it appears to do if syscall is int80 or
211 * SYSCALL64. For SYSCALL32 or SYSENTER, though, this is highly
212 * magical. It needs to work so that ptrace and syscall restart
213 * work as expected.
214 */
215 regs.user_ax = regs.user_syscall_nr;
216 regs.user_ip -= 2;
217 if (ptrace(PTRACE_SETREGS, chld, 0, &regs) != 0)
218 err(1, "PTRACE_SETREGS");
219
220 if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0)
221 err(1, "PTRACE_SYSCALL");
222 wait_trap(chld);
223
224 if (ptrace(PTRACE_GETREGS, chld, 0, &regs) != 0)
225 err(1, "PTRACE_GETREGS");
226
So, it looks like just another ptrace call which will allow program to run until next system call is made by it; then stop child and signal the ptracer. It can read registers, optionally change some and restart the syscall.
Implemented in http://lxr.free-electrons.com/source/kernel/ptrace.c?v=4.10#L1039 like other stepping ptrace calls:
1039 #ifdef PTRACE_SINGLESTEP
1040 case PTRACE_SINGLESTEP:
1041 #endif
1042 #ifdef PTRACE_SINGLEBLOCK
1043 case PTRACE_SINGLEBLOCK:
1044 #endif
1045 #ifdef PTRACE_SYSEMU
1046 case PTRACE_SYSEMU:
1047 case PTRACE_SYSEMU_SINGLESTEP:
1048 #endif
1049 case PTRACE_SYSCALL:
1050 case PTRACE_CONT:
1051 return ptrace_resume(child, request, data);
And man page has some info: http://man7.org/linux/man-pages/man2/ptrace.2.html
PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP (since Linux 2.6.14)
For PTRACE_SYSEMU, continue and stop on entry to the next
system call, which will not be executed. See the
documentation on syscall-stops below. For
PTRACE_SYSEMU_SINGLESTEP, do the same but also singlestep if
not a system call. This call is used by programs like User
Mode Linux that want to emulate all the tracee's system calls.
The data argument is treated as for PTRACE_CONT. The addr
argument is ignored. These requests are currently supported
only on x86.
So, it is not portable and used only for Usermode linux (um) on x86 platform as variant of classic PTRACE_SYSCALL. And um test for sysemu with some comments is here: http://lxr.free-electrons.com/source/arch/um/os-Linux/start_up.c?v=4.10#L155
155 __uml_setup("nosysemu", nosysemu_cmd_param,
156 "nosysemu\n"
157 " Turns off syscall emulation patch for ptrace (SYSEMU) on.\n"
158 " SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
159 " behaviour of ptrace() and helps reducing host context switch rate.\n"
160 " To make it working, you need a kernel patch for your host, too.\n"
161 " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further \n"
162 " information.\n\n");
163
164 static void __init check_sysemu(void)
Link in comment was redirecting to secret site http://sysemu.sourceforge.net/ from 2004:
Why ?
UML uses ptrace() and PTRACE_SYSCALL to catch system calls. But, by
this way, you can't remove the real system call, only monitor it. UML,
to avoid the real syscall and emulate it, replaces the real syscall by
a call to getpid(). This method generates two context-switches instead
of one. A Solution
A solution is to change the behaviour of ptrace() to not call the real
syscall and thus we don't have to replace it by a call to getpid().
How ?
By adding a new command to ptrace(), PTRACE_SYSEMU, that acts like
PTRACE_SYSCALL without executing syscall. To add this command we need
to patch the host kernel. To use this new command in UML kernel, we
need to patch the UML kernel too.

Resources