23 decembrie 2015

"Disable yama" in Ubuntu

 cat /proc/sys/kernel/yama/ptrace_scope 

As Linux grows in popularity, it will become a larger target for malware. One particularly troubling weakness of the Linux process interfaces is that a single user is able to examine the memory and running state of any of their processes. For example, if one application (e.g. Pidgin) was compromised, it would be possible for an attacker to attach to other running processes (e.g. Firefox, SSH sessions, GPG agent, etc) to extract additional credentials and continue to expand the scope of their attack without resorting to user-assisted phishing. This is not a theoretical problem. SSH session hijacking and arbitrary code injection attacks already exist and remain possible if ptrace is allowed to operate as before. Since ptrace is not commonly used by non-developers and non-admins, system builders should be allowed the option to disable this debugging system.

ptrace_scope value 0 => disable this security, while value 1 is the default after each booting

 echo 0 > /proc/sys/kernel/yama/ptrace_scope 

30 august 2015

Interviu cu Intel (internship)

Pozitie : compiler engineer intern

Convorbire #1 :
* despre experienta in domeniul compilatoarelor (proiecte,etc) - ce optimizari s-au facut, cum se face generarea de cod, exemple de instructiuni in limbaj de asamblare, parsare, etc.
* RISC vs. CISC 
* SIMD, cum se poate executa n! = 1*2*..*n in SIMD
* exemplu de dificultate intalnita si cum am rezolvat-o
* experienta cu OOP, probleme rezolvate, exp. cu Java
* cuvantul-cheie static in C
* ce am studiat la arhitectura calculatoarelor, ierarhia de memorii, cum se inlocuiesc datele in memorie, ce ordin de marime au L1, L2, ..
* despre merge sort, complexitate - avg, best case
* sparse bit sets
* hash tables - principiu, cum se mentine echilibrat
* arbori binari - traversare in ordine
* cum se inverseaza cat mai optim un sir de caractere

Convorbire #2 :
* avand o lista simplu inlantuita, cum se poate detecta o bucla? (cu 2 pointeri, apoi cu unul singur)
* intr-un graf neorientat, cum se poate detecta daca exista cale intre doua noduri, cat mai eficient.
* avand 100 numere intregi pozitive, cum se poate afla daca 51 sau mai multe sunt identice, folosind o stiva (analogie: avem o stiva si 100 fructe care sunt mere sau portocale, cum se poate afla)
* BFS vs. DFS - principiu, diferente, implementare

Etapa #3 :
Completarea unor formulare care contin: identificare (SSN, pasaport), statutul legal (viza), mai multe feluri de acorduri (consents), informatii despre resedinta si educatia din ultimii 7 ani, etc.

Etapa #4 :
Convorbire in care este prezentata oferta de munca, urmata de un email cu oferta in format scris, doua email-uri de bun venit si un email in legatura cu CPT.

10 iunie 2015

Probleme pt interviu: C++, Java, Database, Threads

cap. 13 - C/C++                                                                                  

Lucruri de baza:
* clase, mosteniri: by default, clasele sunt private
daca avem class Student : public Person { ... } ; Person p = new Student() ;  => p va fi Person (static binding, in timpul compilarii) . Pentru dynamic binding se foloseste cuvantul-cheie virtual.
* virtual permite suprascrierea cu ultima definitie a tipului declarat 
* virtual destructor va apela destructorul ambelor clase (cea mostenita si cea mostenitoare)
* functiile se pot declara cu valori implicite, la fel ca in Python
* overloading: BookShelf BookShelf::operator+ (BookShelf x)  { ... }     - supraincarcarea operatorului + pentru a fi aplicat si obiectelor de tip BookShelf
* pointeri: int * p = new int; *p = 7;      lungimea pointerului este de 32 sau 64 biti (in functie de tipul masinii)
* tipul referinta: int a = 5; int & b = a; b = 7; cout<<a; // scrie 7  , aici b este un alias pentru a, nu ocupa memorie pt el insusi
* nu este posibila declaratia:  int & b;  
dar e ok: int & b = 12; // b este referinta la locul unde este stocat nr. intreg 12
* templates: reutilizare a codului astfel incat aceeasi clasa sa fie aplicabila la mai multe tipuri de date
template <class T>
class ShiftedClass {
  T * arr;
  int offset, size;
  ... 
}

* o metoda pentru a scrie ultimele K linii dintr-un fisier, folosind C++

Sol.: se foloseste un sir circular de lungime K . Se pastreaza un index al celui mai vechi element si intotdeauna se inlocuieste elementul respectiv cu cel mai nou element(linie) citit.

void printLast (char * filename) {
  const int K = 10; // ultimele 10 linii
  ifstream file (filename);
  string L[K];
  int size = 0;
  while (file.good()) {
    getline ( file, L[size % K] );  // umple vectorul incepand cu cea mai "veche" pozitie
    size++;
  }
  // afla inceputul
  int start;
  if (size > K) start = size % K;  // ce ar fi devenit cea mai "veche" pozitie e acum prima din ultimele K
  else start = 0; // au fost mai putin de K linii
  int count = min (K, size);
  // print the lines
  for (int = 0; i < count; i++) {
    cout<< L [(start+1)%K] << endl;
  }
}


* comparatie intre hash table si un STL map. Cum sunt implementate? Daca nr. de input-uri este mic, care structura de date se foloseste mai bine?

Sol.: 
HashTable: - valorile sunt create apeland o functie de hash asupra valorii
  - valorile nu se salveaza in ordine ASC sau DESC
  - inserarea/cautarea se petrec in O(1)
  - trebuie sa rezolve potentialele coliziuni (adesea se face prin inlantuire, linked list)
  - implementare: un sir de liste inlantuite, cheia corespunde unui index in sir (care se afla folosind functia de hash), valorile intr-o lista inlantuita corespund unei aceleiasi chei, insa trebuie salvata si cheia pentru a furniza valoarea corecta

STL map: - perechea cheie,valoare se insereaza intr-un arbore binar de cautare, in fct de cheie
  - nu este cazul coliziunilor
  - inserare/cautare se petrec in O(log n)

Nr. mic de inputs: STL map sau un arbore binar. Nr. mare: hash table.


* cum functioneaza functiile virtuale in C++?

Sol.: Functiile nevirtuale se rezolva in timpul compilarii, cu static binding
Functiile virtuale se rezolva in timpul rularii, cu dynamic binding. Se salveaza intr-o structura numita vtable, asociata unei clase. Daca functia virtuala nu este suprascrisa, se acceseaza vtable al clasei derivate si adresa functiei se salveaza in clasa-parinte. 


* diferenta intre deep-copy si shallow-copy?

Sol.: Deep-copy: copiaza obiectul intocmai (duplicat), daca se modifica copia, originalul ramane intact. Shallow-copy: opusul.


* ce inseamna volatile in C?

Sol.: Cuvantul-cheie volatile informeaza compilatorul ca valoarea unei variabile se poate schimba din exterior, fara nicio corespondenta in codul sursa (se poate realiza datorita SO, al unui altui thread, sau din hardware). Astfel, compilatorul va trebui sa reincarce valoarea din memorie de fiecare data cand se foloseste variabila, iar astfel este prevenit sa nu faca optimizari care ar schimba logica codului.
int volatile x; // volatile int x;
int volatile * volatile x; // pointer volatil la o variabila volatila


* de ce un destructor ar trebui declarat virtual intr-o clasa care poate fi mostenita?

Sol.: 
Foo * p = new Bar();
La distrugere, fara un destructor virtual, se apeleaza destructorul din Foo, chiar daca p este de tip Bar. Ca "Bar", p ar putea avea campuri noi care nu vor ajunge sa fie distruse pentru ca nu apar in Foo.


* o metoda care face o copie completa a unui pointer la obiectul de mai jos:
struct Node {
  Node * ptr1;
  Node * ptr2;
}
Sol.:
typedef map <Node *, Node *> NodeMap; 
Node * copy (Node * current, NodeMap & nodeMap) {
  // fct recursiva 
  if (current == NULL) return NULL;
  // pt evitarea buclelor infinite de la un ptr care a condus la un ptr deja vizitat
  NodeMap :: iterator i = nodeMap.find(current); // std::pair, are first & second
  if ( i != nodeMap.end() ) {
    return i->second; //  valoarea 
  }
  Node * node = new Node;  // creeaza copia (sau bucata de copie)
  nodeMap[current] = node;  // first = current, second = node (~copia lui current este node)
  node->ptr1 = copy(current->ptr1, nodeMap);
  node->ptr2 = copy(current->ptr2, nodeMap);
  return node;
}

// creare
Node * mainCopy (Node * root) {
  NodeMap nodeMap;
  return copy (root, nodeMap);
}


cap. 14 - Java                                                                                     

Termeni-cheie:
> overloading - doua metode au acelasi nume dar numar diferit de argumente
> overriding - o subclasa redefineste o metoda a parintelui, folosind aceeasi semnatura pentru ea


* ce se intampla cand constructorul unei clase este privat?

R: se asigura faptul ca nimic din afara clasei nu poate instantia direct clasa, astfel singurul mod de a o instantia este folosind o metoda statica si publica (~ Factory Method Pattern)


* try { 
    ...
    return 0;
  }
  catch (Exception e) { ... }
  finally { ... }    // ajunge sa se execute aceasta portiune??

R: Da, finally se executa intotdeauna dupa ce try se termina. Singurele cazuri cand finally nu se executa sunt: masina virtuala se opreste in timpul try/catch sau thread-ul care executa try/catch este omorat.


* final vs. finally vs. finalize

final: cuvant-cheie pentru o variabila constanta SAU o metoda care nu poate fi suprascrisa SAU o clasa care nu poate fi derivata
finally: in try/catch, o portiune de cod care se executa intotdeauna indiferent daca apare exceptie sau nu
finalize: metoda apelata de garbage collector cand isi da seama ca nu mai exista referinte la resurse care trebuie "curatate"


* ce este object reflection? La ce ajuta?

Class rectDef = Class.forName("MyProj.Rectangle");  
rectDef.getConstructor();

Informatii "reflexiva" despre clase si obiecte Java, metode si campuri prezente in timpul rularii; Se pot crea instante noi ale clasei, get/set pe campurile obiectului indiferent de tipul de acces (public/private) . Ajuta la: observarea si manipularea comportamentului la runtime a aplicatiei; pentru depanare si testare.


cap. 15  - Baze de date                                                                      

Baza de date normalizata vs. nenormalizata: minimizarea redundantei vs. optimizarea timpului de citire (si evitarea join-urilor)
Aici exercitiile sunt de tip sql queries (subqueries, join-uri, having/group by, etc) si de tip teoretic.


* care sunt tipurile de join?

R: JOIN se foloseste la combinarea rezultatelor din 2 tabele care au cel putin un camp folosit pentru a face legatura intre ele. 
INNER JOIN: doar randurile unde conditia de join se respecta
OUTER JOIN: INNER JOIN + alte randuri care nu respecta conditia in cel de-al doilea tabel
 - LEFT JOIN: rezultatul contine toate inregistrarile din tabelul din stanga sau NULL daca nu exista valori coresp. in tabelul din dreapta
 - RIGHT JOIN: idem LEFT, dar invers
 - FULL OUTER JOIN: LEFT+ RIGHT


* denormalizare, ce este? pro, contra?

R: O tehnica de optimizare in care adaugam informatii redundante la 1 sau mai multe tabeluri. Ajuta la evitarea join-urilor costisitoare dintr-o baza de date relationala.
Pro: - datele se achizitioneaza mai repede, mai putine join-uri
   - interogarile sunt mai simple, riscul greselilor este mai mic
Contra: - update,insert sunt mai costisitoare si mai dificil de scris
   - datele pot deveni inconsistente
   - din cauza redundantei este nevoie de mai mult spatiu de stocare


* o interogare pt a obtine o lista a studentilor de onoare (top 10%) ordonati dupa medie

Student: sId, name, bday
Coursework: courseId, sId, grade
Course: courseId, courseName

DECLARE @gpaCutOff float;
SET @gpaCutOff = ( SELECT min(GPA) as 'GpaMin' 
                                    FROM  ( SELECT TOP 10 PERCENT AVG (Coursework.grade) as GPA 
                                                    FROM Coursework
                                                    GROUP BY Coursework.sId
                                                    ORDER BY GPA desc) Grades );
SELECT StudentName, GPA
FROM ( 
    SELECT AVG (Coursework.Grade) as GPA, Coursework.sId
    FROM Coursework
    GROUP BY Coursework.sId
    HAVING AVG(Coursework.grade) >= @GpaCutoff
) Honors INNER JOIN Students ON Honors.sId = Student.sId


cap. 16 - Threads & Locks                                                               

Fire de executie in Java:
1) implementeaza Runnable SAU
2) extind Thread
Se prefera Runnable deoarece Java nu accepta mostenire multipla.

Metode synchonized: se executa de catre un singur thread la un moment dat ( al doilea thread care nu are voie sa execute metoda trebuie sa apartina aceleiasi instante a obiectului, altfel are voie )

Lock:  ReentrantLock
Un Lock in Java este proprietatea thread-ului care l-a creat, niciun alt thread nu poate sa-l modifice. Pentru semafoare, nu .


* diferenta intre un proces si un thread

R: Procesul este o instanta a unui program in executie, foloseste CPU si memorie, se executa intr-un spatiu de adrese separat. Procesele nu-si pot accesa spatiile unul altuia, cu exceptia IPC (interprocess communication prin pipes, files, sockets, etc)
Un thread exista in cadrul unui proces, foloseste resursele procesului, inclusiv heap-ul. Mai multe thread-uri ale aceluiasi proces impart acelasi spatiu de heap, insa fiecare thread are propriile registre si spatiu pe stiva.


* cum se poate masura timpul petrecut intr-un context switch?

R: Trebuie masurat timpul dintre ultima instructiune executata de P1 si prima instr. exe. de P2.
Il fortam pe P2 sa execute fix dupa P1, printr-un pipe: P1 trimite, P2 primeste.
Pasii sunt:
- P1 marcheaza timpul de start, T1
- P1 trimite un token la P2, care ia Td pentru a fi livrat
- P1 incearca sa primeasca un raspuns de la P2, se blocheaza si are loc context switch -> Tc
- P2 incepe sa ruleze, primeste token-ul   -> Tr
- P2 trimite un raspuns catre P1, care ajunge in Td
- P2 asteapta un raspuns de la P1, se blocheaza si are loc context switch  ->  Tc
- P1 incepe sa ruleze, primeste token-ul     ->  Tr
- P1 marcheaza timpul de final, T2
=> T = 2 ( Td + Tr + Tc ) , unde T = T2 - T1
=> Tc = ...